std::construct_at 在现有对象之上跳过某些字段的重新初始化
std::construct_at on top of existing object skipping re-initialization of some fields
在下面的程序中,在常量表达式中,创建了一个 A
的临时对象,并初始化了所有字段,然后函数 f
创建了另一个 A
的对象相同的地址,跳过(重新)初始化字段 x
,之后读取:
#include <memory>
struct A {
int x;
constexpr A() {}
constexpr A(int xx) : x(xx) {}
};
constexpr int f(A && a) {
std::construct_at<A>(&a);
return a.x;
}
static_assert( f(A{5}) == 5 ); //ok in GCC only
GCC 接受得很好。但是其他编译器抱怨,例如铿锵声:
note: read of uninitialized object is not allowed in a constant expression
return a.x;
^
演示:https://gcc.godbolt.org/z/87zrEb7q7
确实x
在std::construct_at<A>(&a)
中没有初始化,但是在A{5}
中初始化了。
这里是哪个编译器?
我确信这是 UB,而 GCC 是错误的。
std::construct_at<A>(&a)
创建一个新的 A
对象,因此其中有一个新的 int x
成员。该新对象未初始化。
为了合法,必须有一个特殊的规则,即未初始化的对象可以根据它们占用的内存内容获取值,但我认为不存在这样的规则。 [basic.indet]
没提
在下面的程序中,在常量表达式中,创建了一个 A
的临时对象,并初始化了所有字段,然后函数 f
创建了另一个 A
的对象相同的地址,跳过(重新)初始化字段 x
,之后读取:
#include <memory>
struct A {
int x;
constexpr A() {}
constexpr A(int xx) : x(xx) {}
};
constexpr int f(A && a) {
std::construct_at<A>(&a);
return a.x;
}
static_assert( f(A{5}) == 5 ); //ok in GCC only
GCC 接受得很好。但是其他编译器抱怨,例如铿锵声:
note: read of uninitialized object is not allowed in a constant expression
return a.x;
^
演示:https://gcc.godbolt.org/z/87zrEb7q7
确实x
在std::construct_at<A>(&a)
中没有初始化,但是在A{5}
中初始化了。
这里是哪个编译器?
我确信这是 UB,而 GCC 是错误的。
std::construct_at<A>(&a)
创建一个新的 A
对象,因此其中有一个新的 int x
成员。该新对象未初始化。
为了合法,必须有一个特殊的规则,即未初始化的对象可以根据它们占用的内存内容获取值,但我认为不存在这样的规则。 [basic.indet]
没提