请考虑以下带有struct B
类型字段的聚合的示例U
。该字段的析构函数是私有的,但由于friend
声明对聚合可用,不能从main
函数调用:
class U {
~U() {}
friend struct B;
};
struct B { U v{}; };
int main()
{
B b; //ok everywhere
auto pb = new B; //ok everywhere
delete pb;
pb = new B{}; //ok in GCC, error in Clang
delete pb;
}
如果使用聚合初始化,B{}
则代码仅被 GCC 接受,而 Clang 则报告错误:
error: temporary of type 'U' has private destructor
pb = new B{}; //ok in GCC, error in Clang
^
<source>:2:5: note: implicitly declared private here
~U() {}
^
演示:https : //gcc.godbolt.org/z/c33Gbqfqh
我在https://en.cppreference.com/w/cpp/language/aggregate_initialization 中没有发现任何对“析构函数”的提及。标准是否真的要求聚合字段的析构函数可供聚合的每个潜在用户使用?
标准确实要求访问析构函数。引用 N4861(最后一个 C++20 草案),[dcl.init.aggr]/8说:
类类型的每个元素的析构函数可能从聚合初始化发生的上下文中调用。[注意:该条款确保在抛出异常的情况下可以为完全构造的子对象调用析构函数。— 尾注 ]
为了完整性,[class.dtor]/15说:
[...] 如果可能调用的析构函数被删除或无法从调用上下文访问,则程序格式错误。
[dcl.init.aggr]/8 由DR2227决议添加,首次发布于 C++20。这是一份缺陷报告,因此编译器也应将其应用于以前的标准版本。
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句