在调用基类构造函数时,GCC和Clang不会执行C ++ 17的保证复制省略;有关详细信息,请参见this question和相应的Clang bug report。
针对错误报告,Richard Smith states:
这是标准措辞中的缺陷。初始化基类子对象时,不能保证复制省略,因为基类可以具有与相应完整对象类型不同的布局。
在什么情况下,基类可以通过“使得不可能保证复制省略”的方式而具有“与相应的完整对象类型不同的布局”?有一个具体的例子可以说明这一点吗?
答案 0 :(得分: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) {}
};
C
构造函数初始化其A
子对象,因此B
构造函数无法初始化。 makeB
如何知道是否应该初始化A
?
在这种情况下,复制省略理论上仍然可行。该实现将需要透明地创建makeB
的两个二进制版本,或向makeB
添加一个不可见的参数(即使用构造函数本身使用的技术),以便可以使用{而不初始化B
。但是,这似乎需要对ABI进行不兼容的更改。
标准中可能有或没有缺陷。委员会可能没有预料到这种情况。如果是这样,我很乐意阅读讨论内容,因为它肯定已经留下了书面记录。因此,在委员会做出澄清之前,其意图尚不清楚。如果要在这种情况下要求删除副本,则要对ABI不兼容进行谴责,那么可能需要对标准进行进一步的更改(除非委员会已预见到这种情况并确保所有内容都与之兼容,在这种情况下,应有点纸痕迹。)