c++ - 所有的临时分配都有唯一的地址吗?

标签 c++ constexpr c++20

在阅读 C++ 周刊评论时 video关于 C++20 中的 constexpr 新支持,我发现了一条评论,声称 C++20 允许在 constexpr 上下文中使用 UB。
起初我确信评论是正确的,但我越想越多,我开始怀疑 C++20 的措辞包含一些聪明的语言来实现这种定义的行为。
要么所有的瞬时分配都返回唯一的地址,或者可能是 C++ 中的一些更一般的概念,这使得 2 个不同的分配指针总是(即使在 nonconstexpr 上下文中)比较假,即使在实际运行时分配器可能会给你相同的地址(因为您删除了第一个分配)。
奇怪的是:你只能使用 ==为了比较,< , >失败...
这是在 constexpr 中涉嫌 UB 的程序:

#include <iostream>
static constexpr bool f()
{
    auto p = new int(1);
    delete p;    
    auto q = new int(2);
    
    delete q;
            
    return p == q;
}
int main()
{
    constexpr bool res1 = f();
    
    std::cout << res1 << std::endl; // May output 0 or 1
}
godbolt

最佳答案

这里的结果是实现定义的。 res1根据实现想要如何定义它,可能是假的、真的或格式错误的。这对于等式比较和关系比较都是一样的。
两者 [expr.eq] (为了平等)和 [expr.rel] (对于关系)首先对指针进行左值到右值的转换(因为我们必须实际读取值来进行比较)。 [conv.lval]/3说转换的结果是:

Otherwise, if the object to which the glvalue refers contains an invalid pointer value ([basic.stc.dynamic.deallocation], [basic.stc.dynamic.safety]), the behavior is implementation-defined.


这里就是这种情况:两个指针都包含一个无效的指针值,根据 [basic.stc.general]/4 :

When the end of the duration of a region of storage is reached, the values of all pointers representing the address of any part of that region of storage become invalid pointer values. Indirection through an invalid pointer value and passing an invalid pointer value to a deallocation function have undefined behavior. Any other use of an invalid pointer value has implementation-defined behavior.


脚注如下:

Some implementations might define that copying an invalid pointer value causes a system-generated runtime fault.


所以我们从左值到右值的转换中得到的值是……实现定义的。它可能是实现定义的,使这两个指针比较相等。它可能是实现定义的,导致这两个指针比较不相等(显然所有实现都是如此)。或者它甚至可以以某种方式实现定义,导致这两个指针之间的比较成为未指定或未定义的行为。
值得注意的是,[expr.const]/5 (控制常量表达式的主要规则),尽管拒绝未定义的行为并明确拒绝任何结果未指定的比较( [expr.const]/5.23 ),但没有说明结果是实现定义的比较。
这里没有未定义的行为。什么都可以。这在持续评估期间无疑是非常奇怪的,我们希望看到一套更严格的规则。
值得注意的是,与 p < q ,似乎 gcc 和 clang 拒绝比较,因为它不是常量表达式(这是...允许的结果),而 msvc 认为两者都是 p < qp > q为常量表达式,其值为 false (这也是......也是允许的结果)。

关于c++ - 所有的临时分配都有唯一的地址吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66789487/

相关文章:

c++ - decltype(auto) 是否使尾随返回类型过时?

c++ - C++ 20 [[no_unique_address]]在GCC中的错误?

c++ - 用模板替换constexpr(用于在编译时计算常量)?

c++ - C++ 中编译时浮点除以零

c++ - std::strong_ordering 如何仅适用于零?

c++ - 访问 NULL 指针上的类成员

c++ - clang 和 gcc 中的 Constexpr 复合赋值运算符

c++ - 每次访问这个小部件时,如何在QWidget中保留QSpinBox上的设置值?

C++ win32 设置光标位置

c++ - 从用于 boost deadline_timer 的处理程序访问类数据