C++ 重新解释演员错误还是UB?

C++ 重新解释演员错误还是UB?,c++,language-lawyer,undefined-behavior,reinterpret-cast,C++,Language Lawyer,Undefined Behavior,Reinterpret Cast,考虑以下代码: #include <cstdint> #include <algorithm> std::uintptr_t minPointer(void *first, void *second) { const auto pair = std::minmax( reinterpret_cast<std::uintptr_t>(first), reinterpret_cast<std::uintptr_t&g

考虑以下代码:

#include <cstdint>
#include <algorithm>

std::uintptr_t minPointer(void *first, void *second) {
    const auto pair = std::minmax(
        reinterpret_cast<std::uintptr_t>(first),
        reinterpret_cast<std::uintptr_t>(second)
    );
    return pair.first;
}

这显然不符合代码创建者的意图。这段代码是导致某些UB还是GCC(8)错误?

重新解释的演员阵容定义良好。问题是
const std::pair
因为这是返回的,所以您有悬空引用

您只需删除悬而未决的引用即可使其正常工作:

std::uintptr_t minPointer(void *first, void *second) {
    const std::pair<std::uintptr_t, std::uintptr_t> pair = std::minmax(
        reinterpret_cast<std::uintptr_t>(first),
        reinterpret_cast<std::uintptr_t>(second)
    );
    return pair.first;
}
std::uintptr\u t minPointer(void*第一,void*第二){
常数std::pair pair=std::minmax(
重新解释铸造(第一次),
重新解释演员阵容(第二)
);
返回对。第一;
}

这是UB,但不是因为你可能认为的原因

其相关签名为:

然后我们没有任何悬而未决的引用,您可以看到gcc生成了适当的代码:

minPointer(void*, void*):
  cmp rsi, rdi
  mov rax, rdi
  cmovbe rax, rsi
  ret
或者,您可以将
pair
的类型显式指定为
std::pair
。或者干脆完全避开这对,返回std::min(…)



就语言细节而言,允许您将指针转换为足够大的整数类型,因为
std::uintpttr\t
保证足够大。所以,一旦你解决了悬而未决的参考问题,你就没事了

好吧,你根本不能使用
(见下面的评论,但仍然有些关联)@下划线\u我同意贾斯汀的观点。然而,您删除的内容仍然非常有趣,我不知道itrelated:/-&cppreference for
minmax
notes-有点低-“对于重载(1,2),如果其中一个参数是右值,则返回的引用在包含调用“另一个:(扰流板:结构化绑定无法避免这种情况,因为如果将类型声明为值,则适用于不可见的
,而不是其成员)我们确实需要C++中的生命依赖标记。@ YAKK ADAMNEVRAUMONT自定义的衰减机制也会很有趣,所以我们可以指定“<代码>配对> /CODE >是<代码>配对> />代码,而不是<代码>配对<代码>这里。这是一个在回想中显而易见的事情,但也很容易忘记,只有一次,FATA。l结果:/@Barry
std::pairminmax(T const&[[life]],T const&[[life]])
(这里的属性可能不合适),它说明返回值的有效生存期取决于两个输入参数的生存期。编译器可以(A)生命周期扩展绑定到输入参数的临时变量,或(b)拒绝使用不安全的悬挂引用。返回类型的更改取决于调用上下文,这似乎比这种标记更难。我希望编译器对此发出警告
template< class T > 
std::pair<const T&,const T&> minmax( const T& a, const T& b );
return std::minmax(
    reinterpret_cast<std::uintptr_t>(first),
    reinterpret_cast<std::uintptr_t>(second)
).first;
minPointer(void*, void*):
  cmp rsi, rdi
  mov rax, rdi
  cmovbe rax, rsi
  ret