【问题标题】:Initializer list seems to be dependent on the order of variables in a class初始化列表似乎取决于类中变量的顺序
【发布时间】:2019-04-10 17:19:16
【问题描述】:

我是 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++ class g++ llvm-clang initializer-list


    【解决方案1】:

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

    class Base {
        public:
            Base();
    
        private:
            string monkey2 = "";
            string monkey1 = "";
    };
    

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

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

    monkey2monkey1 初始化,但是由于声明的顺序,monkey1 在这一点上没有初始化,因为monkey2 首先被初始化。这就是您收到警告的原因,这也是为什么通过首先声明 monkey1 来减轻警告的原因 - 然后,monkey1 通过类内初始化程序设置为 ""monkey2 使用已经初始化的 @ 进行初始化987654336@.

    以下(当然是主观的)指南适用于这种情况:

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-04-13
      • 1970-01-01
      • 2018-12-19
      • 1970-01-01
      • 1970-01-01
      • 2013-05-29
      • 2010-09-17
      相关资源
      最近更新 更多