为什么私有成员的默认构造函数没有被调用?

4

我将我的问题简化为以下代码:

#include<iostream>
#include<stdio.h>
#include <list>
using namespace std;
class B
{
public:
    B(){
        cout<<"Default ctor of B"<<endl;
    };
};

class C
{
public:
    C()
    {
        cout<<"Default ctor of C"<<endl;
    }
    void sayHello()
    {
        cout<<"Say hello"<<endl;
    }
};
class A: public B
{
public:
    void fun()
    {
        c.sayHello();
    }
private:
    C c;
};

int main(int argc, char** argv)
{
    A* a=new A();
    a->fun();
    delete a;
    return 0;
}

当我创建A对象时,我发现没有调用默认构造函数C,但当我调用A::fun()时,它可以正确地调用C::sayHello()。这怎么可能呢?我在特定的工具链下进行了交叉编译,但是如何可能分配对象内存并不调用其默认构造函数的主体?这似乎是明显的编译器错误,难道不是吗?
当我在Fedora上使用GCC编译上述代码时,一切都按预期工作。
编辑:编译器是为Broadcom芯片集成量身定制的GCC-4.2。在执行代码时存在问题的嵌入式系统中,解决方法是向A添加默认的空构造函数。
A(){}

即使在初始化列表中没有明确调用C++对象的默认构造函数也可以进行初始化。

3
哪个gcc版本?听起来像是有缺陷的编译器。在4.8版本上工作正常。 - BЈовић
1
在MSVC下工作。这里可能有一些cout的怪癖在起作用吗? - Grimm The Opiner
你应该把那个信息放在问题里。 - juanchopanza
@user1158692 - 这与cout无关,我在这里只是为了演示目的使用它。在原始代码中,我通过查看sayHello()方法中的一些类B成员是否以应该被调用的方式初始化来观察问题。 - flyjohny
@flyjohny 对于 cout 的看法很公正。如果您在 C 的构造函数中设置断点会发生什么? - Grimm The Opiner
显示剩余7条评论
1个回答

1

@juanchopanza正确地指出,对于编译器来说,延迟调用C的构造函数不符合标准行为。 "对象在其构造函数完成之前不被认为已构造。"(Stroustrup,《C++程序设计语言》,第3版,第366页)。

然而,在这里可能存在另一个微妙之处,涉及到默认构造函数和所谓的值初始化之间的区别。请参阅以下两个先前的StackOverflow答案:

根据您的编译器是否将C视为POD类型以及它是否符合C++98或C++03标准,它可能会执行值初始化而不是默认构造函数。添加用户声明的默认构造函数到A中会改变行为,这是一个提示,表明此问题正在发挥作用。


如果 C 有一个用户定义的构造函数,它就不能是 POD。这只是编译器的错误。 - Jonathan Wakely
@Daniel Hardman - 这很有趣。C不是POD,但这个关于值初始化的建议似乎在这里适用。然而,正如先前提到的,这必须是编译器的错误。但我给你一个有趣的观点的赞成票。 - flyjohny

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接