gpt4 book ai didi

c++ - 析构函数必须对默认初始化的类成员才可用(公共(public))还是完全有效?

转载 作者:行者123 更新时间:2023-12-04 11:29:20 28 4
gpt4 key购买 nike

请考虑一个结构 A有一个字段 u类型 U<R>带有默认初始化程序。析构函数 ~U<R>仅声明:

template<typename T>
struct U {
~U();
};

struct R;

struct A {
U<R> u = U<R>{};
};
所有编译器都接受此代码,演示: https://gcc.godbolt.org/z/oqMjTovMo
但是如果我们定义析构函数 ~U<R>如下:
template<typename T>
struct U {
~U() { static_assert( sizeof(T) > 0 ); }
};

那么当前的编译器就会出现分歧。 MSVC 不断接受程序,而 GCC/Clang 打印错误
error: invalid application of 'sizeof' to an incomplete type 'R'
演示: https://gcc.godbolt.org/z/713TzPd6v
显然,编译器必须验证默认初始化类成员的析构函数的可用性,以防在构造过程中发生异常。但是标准是否要求编译器只检查析构函数的可用性(就像 MSVC 那样),或者编译器也应该验证它的主体? MSVC 的行为在这里看起来更方便,因为它允许 R 的前向声明由 struct A 的那一刻起定义。
P. S. 这个探索不仅有纯粹的理论兴趣。如果换成 U这里有 std::unique_ptr然后解释了为什么类字段类型为 std::unique_ptr<R>对于不完整的类,被 MSVC 接受并被 GCC/Clang 拒绝 R .

最佳答案

[dcl.init.aggr]/8 :(强调我的)

The destructor for each element of class type is potentially invoked ([class.dtor]) from the context where the aggregate initialization occurs.


[basic.def.odr]/8 :

A destructor for a class is odr-used if it is potentially invoked.


[basic.def.odr]/10 :

Every program shall contain exactly one definition of every non-inline function or variable that is odr-used in that program outside of a discarded statement; no diagnostic required.


所以 ~U()可能在 U<R> u 处被调用内 A ,这需要它的定义。
然后根据 [temp.inst]/4 :

Unless a member of a class template or a member template is a declared specialization, the specialization of the member is implicitly instantiated when the specialization is referenced in a context that requires the member definition to exist ...


附注:当然,它实际上是 invoked每当 A 的实例时被摧毁。所以需要编译。
注意:在第一个版本中,编译器接受代码,因为析构函数不是内联的,因此它在链接期间失败( example )。
至于MSVC接受代码,似乎是个bug。

关于c++ - 析构函数必须对默认初始化的类成员才可用(公共(public))还是完全有效?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/68870677/

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