【发布时间】:2022-10-02 04:13:00
【问题描述】:
在下面的程序中,constexpr 函数foo() 使用字段x=1 生成A 的对象,然后在其之上使用std::construct_at 和默认初始化x=x 构造另一个对象,然后是常量评估值打印:
#include <memory>
#include <iostream>
struct A {
int x = x;
};
constexpr int foo() {
A a{1};
std::construct_at<A>(&a);
return a.x;
}
constexpr int v = foo();
int main() {
std::cout << v;
}
GCC 在这里打印1。 Clang 和 MSVC 都打印 0。只有 Clang 发出警告:field \'x\' is uninitialized when used。演示:https://gcc.godbolt.org/z/WTsxdrj8e
程序中是否存在未定义的行为?如果是,为什么在持续评估期间没有编译器检测到它?如果不是,哪个编译器是正确的?
-
你做(直接)list initialization 的聚合(导致aggregate initialization),这将copy initialize 成员
x。所以默认初始化不应该发生。似乎 GCC 是正确的,而其他的都是错误的。 -
@Someprogrammerdude 在您描述的 UB 之后有
std::construct_at<A>(&a);。 @OP 编译器不是万能的,这里的 UB 隐藏在construct_at下。最近在 SO 上还有一个问题,编译器不会在 constexpr 函数中的 constexpr 对象上的construct_at上说任何话。 -
有什么理由相信这与 stackoverflow.com/q/70820127/7325599 和 gcc.gnu.org/bugzilla/show_bug.cgi?id=104192 不同。它仍然看起来涉及不确定值的左值到右值转换(现在在初始化而不是在返回中),另一个 SO 答案暗示这是 IFNDR。因此不需要诊断。
-
在另一个问题中,Clang 和 MSVC 以
expression did not evaluate to a constant错误拒绝该程序,并且这里所有编译器都接受该代码,尽管产生了不同的结果。
标签: c++ language-lawyer undefined-behavior constexpr