初始化程序列表似乎取决于类中变量的顺序

时间:2018-11-07 09:34:45

标签: c++ class g++ llvm-clang initializer-list

我是C ++的新手,这是我在这里的第一篇文章。我正在尝试了解初始化程序列表。问题是我越来越困惑。我做了一个简单的程序,没有用,但是我得到一个我不明白的警告。

#include <iostream>

using namespace std;

class Base{

    private:
        string monkey2 = "";
        string monkey1 = "";
    public:
        Base(string) : monkey2{monkey1}{
            cout << "monkey1 " << monkey1 << endl;
            cout << "monkey2 " << monkey2 << endl;
        }
};

int main()
{
    return 0;
}

我得到的警告是:

field 'monkey' is uninitialized when used here

和指向public:正下方的行上的箭头。

奇怪的是,如果我更改以下字符串的顺序:

private:
    string monkey2 = "";
    string monkey1 = "";
public:

收件人:

private:
    string monkey1 = "";
    string monkey2 = "";
public:

警告消失了,我不明白为什么。我可以使用g ++进行编译,但是将我的编辑器vim与YCM和Clang 7.0.0一起使用时,会出现警告。我试图在g ++中激活尽可能多的警告,但是无法获得相同的警告。是我的代码还是。还是Clang?

1 个答案:

答案 0 :(得分:1)

数据成员按照声明的顺序进行初始化。因此,当您拥有

class Base {
    public:
        Base();

    private:
        string monkey2 = "";
        string monkey1 = "";
};

无论变量monkey2做什么,变量monkey1都将在之前 Base::Base()初始化。当数据成员的初始化相互依赖时,这可能导致很难发现问题。在这里,

Base() : monkey2{monkey1} { /* ... */ }

monkey2monkey1初始化,但是由于声明的顺序,monkey1尚未初始化,因为monkey2首先被初始化。这就是收到警告的原因,也是通过首先声明monkey1来减轻警告的原因-然后,通过类内初始化程序和{{1}将monkey1设置为"" }使用已初始化的monkey2进行初始化。

以下(公认的主观)准则适用于这种情况:

  • 如果可以避免跨数据成员的初始化依赖关系,请这样做。
  • 如果有ctor初始化程序列表,请严格遵循声明数据成员的顺序(请参见C.47)。
  • 如果数据成员存在合理的默认值(可能跨ctor重载,请使用类内初始化)(但是,请勿像在monkey1实现中那样添加其他初始化指令(请参阅{{3 }}。