0

在下面的代码中,我在创建基类时为未初始化的类成员赋值。为什么这不会导致运行时错误?

class Foo {
public:
    Foo(std::string) {}
};

class Bar : public Foo {
public:
    Bar() : Foo(s = f()) {} // assigning to uninitialized class member

    void print() { 
        std::cout << s << std::endl; 
    }
    std::string f() {
        return "Some string";
    }

private:
    std::string s;
};

int main()
{
    Bar b;
    b.print();
    return 0;
}

但是向类 Bar 添加另一个成员会在创建 Foo 类时产生错误:

Class Bar {

// same as above

private:
    std::string s;
    int a;        // adding another member
};

为什么会发生这种情况?

4

4 回答 4

1

“运行时错误”?分配给未初始化的成员时没有“运行时错误”。在 C++ 中,“未初始化”状态在运行时是不可检测的,这就是为什么它不可能以任何确定的方式处理(如“运行时错误”)。

当您执行类似操作时,您的代码会表现出未定义的行为。这种未定义的行为将表现出来是不可预测的。它很容易对完全不相关的因素敏感,比如在类中声明另一个成员。这里的所有都是它的。

于 2013-09-10T15:49:21.510 回答
0

我试图调试你的代码。看来,当你写:

Bar() : Foo(s = f()) {}

s对象尚未正确创建。因为构造函数调用Foo()还没有完成。基本上它处于未定义状态。所以任何行为都是不确定的。但是这个代码行为不是未定义的:

Bar() : Foo(/*anything*/) {
        s = f();
    } 

因为构造函数调用完成了。


注意:我在msvc11中测试过

于 2013-09-10T15:34:57.477 回答
0

当 f() 执行时,类 Bar 未初始化,因此成员 'a' 没有值。有趣的是,这段代码在 Visual Studio 2008 中运行,但无论如何这都不安全。

拉兹万。

于 2013-09-10T15:35:14.883 回答
0

基类和类成员按声明顺序初始化(虚基类不同):

  • 基类(第一个)按声明顺序排列(例如 class X : A, B, C }
  • 按声明顺序排列的成员(例如 int a;int b;int c;)

构造函数中初始化的顺序不会改变它。

在您的情况下, Foo 未初始化,因此 Bar 及其成员 - 未定义的行为( s 在分配给它时有一些垃圾数据)。

于 2013-09-10T15:35:56.473 回答