什么时候基类可以具有与相应完整对象类型不同的布局?

pyc*_*che 13 c++ c++17

当调用基类构造函数时,GCC和Clang不会执行C ++ 17的保证复制省略。有关详细信息,请参见此问题和相应的Clang错误报告

针对错误报告,Richard Smith指出

这是标准措辞中的一个缺陷。初始化基类子对象时,不能保证复制省略,因为基类可以具有与相应完整对象类型不同的布局。

在什么情况下,基类可以以“无法保证复制省略”的方式具有“与相应完整对象类型不同的布局”?有一个具体的例子可以说明这一点吗?

n. *_* m. 6

每当涉及虚拟继承时。

例:

struct A {
   int a;
   A (int a) : a(a) {}
};

struct B:  virtual A {
   B() : A(0) {}
};


B makeB { return B(); }

struct C : B {
  C() : B(makeB()), A(42) {}
};
Run Code Online (Sandbox Code Playgroud)

C构造函数初始化其A子对象,所以B构造函数不能。怎么makeB知道是否应该初始化A

在这种情况下,理论上仍可以进行复制省略。该实现将需要透明地创建的两个二进制版本makeB,或向其中添加不可见的参数makeB(即使用构造函数本身使用的技术),以便它可以在B初始化时进行或不进行初始化A。但是,这似乎需要对ABI进行不兼容的更改。

标准中可能有也可能没有缺陷。委员会可能没有预料到这种情况。如果是这样,我很乐意阅读讨论内容,因为它肯定已经留下了书面记录。因此,在委员会做出澄清之前,其意图尚不清楚。如果要在这种情况下要求删除副本,则要对ABI不兼容进行谴责,那么可能需要对标准进行进一步的更改(除非委员会已预见到这种情况并确保所有内容都与之兼容,在这种情况下,应有点纸痕迹)。