c ++ 11什么是第一个?构造函数或默认值?

时间:2014-05-29 07:29:26

标签: c++11 constructor initialization

在c ++ 11中,你可以这样做:

class Foo
{
    public:
        Foo();
        bool test = false;
};

Foo::Foo()
{
    // is test guaranteed to be false now? and is it surely not overriden later?
    this->test = true;
}

我想知道的内容基本上是在评论中描述的,我可以用我的编译器来验证这一点,但这是在标准中提到的吗?它在所有平台和所有编译器上是否总是相同的?

3 个答案:

答案 0 :(得分:2)

现在测试保证是假的吗?是。

以后肯定不会覆盖吗?它不会被覆盖。默认值设置为构造函数开头的初始化列表的一部分。

如果初始化列表中没有包含test,则编译器会将其置于默认值中。对于构造函数,编译器实际上会为此生成代码:

Foo::Foo()
    : test(false)
{
    // is test guaranteed to be false now?
    this->test = true;
    // is it surely not overriden later?
}

使用此构造函数测试将首先初始化为false,然后在body中设置为true。

如果你写了:

Foo::Foo()
    : test(true)
{
}

测试将在初始化列表中,并且编译器不会将其放在那里,测试将直接初始化为true。

答案 1 :(得分:2)

在C ++ 11中,有三个地方可以初始化非静态数据成员:

  • 在类的主体中(支撑或等于初始化器
  • 在构造函数体之前的成员列表中( mem-initializer
  • 在构造函数体内。

如果非静态数据成员同时具有大括号或等于初始化 mem-initializer ,那么 mem-initializer 覆盖 brace-or-equal-initializer ;这在12.6.2.p9中指定。

在任何一种情况下,非静态数据成员的初始化都在输入构造函数体之前发生,因此构造函数可以改变成员的值。

答案 2 :(得分:2)

来自[ class.base.init ] 12.6.2 - 初始化基础和成员

  

9 如果给定的非静态数据成员同时具有大括号或等于初始化程序,    mem-initializer ,执行mem-initializer指定的初始化,   并忽略非静态数据成员的 brace-or-equal-initializer

实施例

struct A
{
  int i = /∗ some integer expression with side effects ∗/ ;
  A(int arg) : i(arg) { } // ...
};

A(int)构造函数只会将i初始化为arg的值,并且i 中的副作用会支持 - 或 - <_p>将不会发生等于初始化

  

10 在非委托构造函数中,初始化在以下进行   顺序:

     
      
  • 首先,仅适用于派生程度最高的类(1.8)的构造函数,   虚拟基类按它们在深度优先上显示的顺序进行初始化   从左到右遍历基类的有向无环图,其中   “从左到右”是派生类中基类出现的顺序   基符列表
  •   
  • 然后,直接基类按声明顺序初始化   出现在 base-specifier-list 中(无论顺序如何    MEM-初始化)。
  •   
  • 然后,按照声明的顺序初始化非静态数据成员   类定义(再次与 mem-initializers 的顺序无关)。
  •   
  • 最后,执行构造函数体的复合语句。
  •   

所以

class Foo
{
public:
  Foo();
  bool test = false;
};

Foo::Foo()
{
  // is test guaranteed to be false now? and is it surely not overriden later?
  this->test = true;
}

test保证为false并且不会被覆盖(&#34;最后,构造函数体的复合语句被执行&#34; < / em>的)