首页 > 解决方案 > 初始化列表似乎取决于类中变量的顺序

问题描述

我是 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?

标签: c++classg++llvm-clanginitializer-list

解决方案


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

class Base {
    public:
        Base();

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

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

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

monkey2由 初始化monkey1,但由于声明的顺序,monkey1此时未初始化,因为monkey2首先初始化。这就是您收到警告的原因,这也是为什么通过monkey1首先声明来减轻警告的原因 - 然后,通过类内初始化程序monkey1设置为,并使用已经初始化的.""monkey2monkey1

以下(诚然是主观的)准则适用于这种情况:

  • 如果您可以避免跨数据成员的初始化依赖关系,请这样做。
  • 如果您有 ctor 初始化器列表,请严格遵循声明数据成员的顺序(参见C.47)。
  • 如果数据成员有一个合理的默认值,可能跨越 ctor 重载,请使用类内初始化(但是,不要像在您的Base::Base(string)实现中那样添加另一个初始化指令(参见C.48)。

推荐阅读