背景
强制复制/移动操作可能已经为许多C++程序员所熟悉。从链接文本复制的示例。编译器不得插入副本和移动:
T =T(T(f();//只调用T的默认构造函数来初始化x
这只能在已知被初始化的对象不是潜在重叠的子对象时才适用:
结构C{ /* .* };C();struct D;D();struct D:C{D():C(f()) {} // no省略,当初始化基类子对象D(int):D(g()) {} / no省略时,因为初始化的D对象可能是其他类}的基类子对象;
在实践中,这是通过给f一个隐藏的额外参数来实现的,它告诉f在哪里构造它的返回值。
问题
为什么潜在重叠的子对象而不是服从强制省略?f没有理由不能直接在D的基类部分构造它的返回值。
发布于 2022-09-10 15:07:41
相关资源如下
以下几点:
f()将调用完整对象(C1)构造函数,而不是基对象(C2)构造函数。这立即排除了对于C具有虚拟基(在这种情况下是C1 != C2)的情况下的复制省略。C是POD (在Itanium的情况下)。然而,这是不切实际的保证,因为有时机器指令更有效率时,包括填充,有ABI的考虑,等等。你的反对意见
D的成员还没有初始化
并不完全正确,因为虚拟基类是在完整对象的末尾分配的:
struct A {
char i = 5;
A() {} // to prevent this being a POD for the purpose of layout
};
struct C {
int j; char s;
C() { /* ...*/ }
};
struct D : virtual A, C {
D() : A(), C(f()) {}
};在这里,A立即在内存中跟随C。稍后,当为f或C的ctors生成代码时,我们无法知道C是否是一个包含虚拟基的完整对象的基。如果让f构造基本对象(在构造A之后发生),我们可能会覆盖重复使用的尾部填充,这就是i所在的位置。
我建议阅读上文第二个环节中的讨论,因为它还涉及切点和修改措辞的方式,以反映目前的实施做法。
https://stackoverflow.com/questions/73559242
复制相似问题