在 C++ 中创建聚合的代码必须使用聚合字段析构函数吗?

用户5545734

请考虑以下带有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] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

聚合字段构造函数必须是公共的才能在 C++ 中使用聚合初始化吗?

析构函数会自动在C ++中调用delete []吗?

这个C ++析构函数是多余的吗?

C ++中的析构函数直接调用

C ++中的纯虚拟析构函数

C ++析构函数中的堆栈溢出

析构函数中的c ++异常

析构函数在C ++中调用向量

C ++中的循环链表的析构函数?

C ++在析构函数中杀死线程

C ++中的“隐式析构函数”

C ++使用RAII与引发的析构函数

在C ++中从构造函数中显式地调用析构函数是不好的做法吗?

C++ 你能在构造函数或析构函数中引用 this 指针吗?

C ++破坏顺序:在类析构函数之前调用字段析构函数

为什么 C++ 中类字段的默认初始化需要析构函数调用?

删除析构函数中由new在C ++中的方法创建的类的成员

C ++:使用仅具有属性的继承结构时需要实现虚拟析构函数吗?

C ++构造函数/析构函数调用&在动态创建的数据上调用“ new”会删除旧数据吗?

[c ++]缺少析构函数

C ++析构函数约定

链表析构函数C ++

覆盖析构函数-C ++

C ++。在析构函数中调用虚拟成员函数

C ++中的析构函数和构造函数排序

我们什么时候必须在派生类c ++中定义一个析构函数

如何释放正在返回的变量所占用的内存(使用C ++,在类中,使用析构函数)?

从C ++中的析构函数中恢复对象?

在Java中使用C ++中的析构函数实现相同的结果