gpt4 book ai didi

c++ - 常量求值器必须拒绝 C++ 中的未定义行为( union 示例)吗?

转载 作者:行者123 更新时间:2023-12-05 08:04:03 24 4
gpt4 key购买 nike

据我所知,未定义的行为应该是不断评估期间的编译错误。

但是如果从 C++20 标准中举一个未定义行为的例子 class.union#6.3稍作修改以激活持续评估:

struct X { const int a; int b; };
union Y { X x; int k; };
constexpr bool g() {
Y y = { { 1, 2 } }; // OK, y.x is active union member ([class.mem])
int n = y.x.a;
y.k = 4; // OK: ends lifetime of y.x, y.k is active member of union
y.x.b = n; // undefined behavior: y.x.b modified outside its lifetime,
// S(y.x.b) is empty because X's default constructor is deleted,
// so union member y.x's lifetime does not implicitly start
return y.x.b > 0;
}

int main() {
static_assert( g() );
}

然后它被所有编译器接受而没有任何警告。演示:https://gcc.godbolt.org/z/W7o4n5KrG

这里是不是所有的编译器都错了,或者示例中没有未定义的行为,或者不需要诊断?

最佳答案

在 C 和 C++ 标准的原始版本中,短语“未定义行为”的意思无外乎是“标准不强加任何要求”。标准没有必要确保每个可能构造的每个可能执行都具有明确定义的行为,或者易于明确地识别为调用未定义行为。

C 和 C++ 草案都明确指出,在标准未强加任何要求的情况下,实现可以“以环境特征的文档化方式”运行。如果在某些执行环境中,缓存行的大小是 int 的两倍,并且将 int 值存储到缓存行的前半部分并将其余部分置零会更快比仅更新高速缓存行的前半部分而保持其余部分不受干扰所需的读-修改-写序列,该平台的实现可能会以某种方式处理写入 y.k 的行为干扰与 y.x.b 关联的存储。另一方面,对于大多数环境,编写 y.k 的“特征行为”将是修改 int 大小的存储 block ,同时将剩余的存储关联 union 不受干扰。

将写入 y.k 然后读取 y.x.b 作为 UB 的行为旨在允许实现处理对 y.k 的写入最快的方式,无需考虑代码是否关心 y.x.b 的内容。它无意要求实现做出任何努力来阻止代码在编写 y.k 之后访问 y.x.b。尽管 C++ 要求模板扩展中的整数常量表达式在调用某些操作时被视为替换失败,而标准不会对其施加任何要求,但要求将所有此类操作视为替换失败会产生矛盾,而标准可以被解释为既要求编译器进行特定的模板替换,又要求编译器避免这样做。

关于c++ - 常量求值器必须拒绝 C++ 中的未定义行为( union 示例)吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/70232491/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com