构造所有基类是否不需要默认生成的构造函数? 我遇到过一个类型,安全C++产生不匹配的cto/dor。 下面的代码为A生成了两个构造函数。默认构造函数也构造了它的基(B),但是默认生成的复制/移动构造函数不构造B。稍后,它会销毁B,因此我们得到不匹配的构造函数/dtor

构造所有基类是否不需要默认生成的构造函数? 我遇到过一个类型,安全C++产生不匹配的cto/dor。 下面的代码为A生成了两个构造函数。默认构造函数也构造了它的基(B),但是默认生成的复制/移动构造函数不构造B。稍后,它会销毁B,因此我们得到不匹配的构造函数/dtor,c++,inheritance,gcc,clang,default-copy-constructor,C++,Inheritance,Gcc,Clang,Default Copy Constructor,我用gcc和clang试过,但都失败了。在gcc bug报告论坛上,他们建议这不是gcc的问题。 我可能遗漏了一些东西,但当类型安全代码导致对尚未构造的类的dtor调用时,难道没有什么奇怪的地方吗 程序输出: B()->插入:0x7fff55398b2f ~B()->擦除:0x7fff55398b2f ~B()->ERASE:0x7fff55398b40/隐式定义的复制构造函数正在创建一个B。当然,这不是调用B::B()。如果添加以下构造函数: B(const B& other) : B

我用gcc和clang试过,但都失败了。在gcc bug报告论坛上,他们建议这不是gcc的问题。 我可能遗漏了一些东西,但当类型安全代码导致对尚未构造的类的dtor调用时,难道没有什么奇怪的地方吗

程序输出:
B()->插入:0x7fff55398b2f
~B()->擦除:0x7fff55398b2f

~B()->ERASE:0x7fff55398b40/隐式定义的复制构造函数正在创建一个
B
。当然,这不是调用
B::B()
。如果添加以下构造函数:

B(const B& other) : B()
{
    *this = other;
}
您将看到输出:

B() -> INSERT: 0x7ffe57ef918f
B() -> INSERT: 0x7ffe57ef91b0
~B() -> ERASE: 0x7ffe57ef918f
~B() -> ERASE: 0x7ffe57ef91b0

重要的一点是:每个构造函数都完全构造对象。默认情况下,复制构造函数不会调用默认构造函数(显然,反之亦然)。因此,如果您在每个构造函数中都需要执行某些操作,那么您必须在每个构造函数中显式地执行这些操作,无论是通过直接调用还是通过构造函数链接。

您所说的确实解决了这一问题,但我仍然感到惊讶的是,如果您忘记为B定义复制/移动构造函数,那么您就可以获得类型安全代码(无强制转换等)这破坏了未构建的记忆!在我看来这是个问题。有没有一些C++大师可以指出这一点(也许是你自己)?“他们也许能澄清它或是把它泡出来。”user2059893编辑后进行了一点阐述。这里没有未构建的内存。隐式复制构造函数仍然是构造函数。@user2059893从未对未构造的对象调用析构函数。构造隐式复制构造函数创建的对象。它只是不调用默认构造函数中的代码。它仍然使用有效的
这个
指针创建一个对象,当它离开作用域时,它仍然会调用它的析构函数。也许你所说的“构造”是指不同的东西。如果你的意思是一个对象是“构造的”,如果它调用默认构造函数中的代码,那么它是“未构造的”,但最好说它没有正确初始化。@user2059893:“我仍然很惊讶,如果一个人忘记为B定义一个复制/移动构造函数,那么你就可以得到类型安全的代码(没有强制转换等)这破坏了未构建的记忆!——这就是习语喜欢并存在的原因。你需要学习它们。然后学习使用RAII包装器,这样你就不必太担心那些规则,因为它们可以为你处理。
B(const B& other) : B()
{
    *this = other;
}
B() -> INSERT: 0x7ffe57ef918f
B() -> INSERT: 0x7ffe57ef91b0
~B() -> ERASE: 0x7ffe57ef918f
~B() -> ERASE: 0x7ffe57ef91b0