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

请帮我完成这个程序:

struct U { 
    U(int *) noexcept;
private:
    ~U() noexcept;
};

struct B {
    B();
    ~B();
    U v; //ok
    U w{nullptr}; //ok
    U u = nullptr; //error
};

这里 structU有一个私有的析构函数,只是为了演示析构函数并不是真正被编译器调用的,也是为了简化代码的长度。

而且structB只声明了一个默认的构造函数和析构函数,所以编译器不会在这个翻译单元中生成它们。

structB也有 3 个字段:v,wu. vw字段没有问题,但是对于字段u,编译器会发出有关无法访问的析构函数的错误U

error: 'U::~U()' is private within this context
   13 |     U u = nullptr; //error

演示:https : //gcc.godbolt.org/z/YooGe9xq6

问题是:

  1. 如果B::B()没有在这个翻译单元中编译,为什么要考虑字段默认初始化?
  2. 错误是因为为u字段的初始化创建了一个临时对象吗?(没有强制复制省略?)
  3. 那么uwcase 有什么区别呢?

回答

如果 B::B() 没有在这个翻译单元中编译,为什么要考虑字段默认初始化?

因为成员初始化是类定义的一部分。因此,类定义本身是无效的,而不必涉及其构造函数的定义。在标准中,您可以从[class.mem.general]开始并遵循brace-or-equal-initializer,这最终需要一个有效的“沼泽标准”赋值表达式。

错误是因为为 u 字段的初始化创建了一个临时对象吗?(没有强制复制省略?)

是的,你的 Godbolt 链接中的编译器错误很清楚:

<source>:13:11: error: temporary of type 'U' has private destructor
    U u = nullptr; //error

请参阅为什么 C++ 中的强制 RVO 需要公共析构函数?解释为什么强制复制省略不适用(谢谢@NathanPierson!)

那么 u 和 w 情况有什么区别呢?

w直接初始化而无需事先创建临时文件,因此创建它可以正常工作,因为表达式中没有任何内容试图调用U. 显然, 的任何定义B::~B()仍然会在 上失败w,但这已经超出了重点。


以上是为什么C++中类字段的默认初始化需要析构函数调用?的全部内容。
THE END
分享
二维码
< <上一篇
下一篇>>