17 October 2022

C++ 核心指南目录

C.48: Prefer default member initializers to member initializers in constructors for constant initializers

理由

这样可以明确表示:所有构造函数中都用一样的值初始化成员变量。可以避免重复,减少代码维护时候遇到的问题,使得代码更短更高效。

例子

class X {   // BAD
public:
    int i;
    string s;
    int j;
    X() :i{666}, s{"qqq"} { }   // j is uninitialized
    X(int ii) :i{ii} {}         // s is "" and j is uninitialized
    // ...
};
X x1{};
cout << x1.i << "\t" << x1.s << "\t" << x1.j << endl;
X x2{11};
cout << x2.i << "\t" << x2.s << "\t" << x2.j << endl;

666 qqq 66 11 24

后期维护代码的人怎么会知道你是故意不把 j 初始化,还是因为其他什么原因?是有意给 s 赋值一个默认的空字符串吗?那 qqq 是不是一个 bug ?像 j 这样的没初始化的变量往往是后期修改代码的时候增加了变量,变量虽然增加了,却忘记把它添加到初始化列表里。

例子

class X2 {
public:
    int i {666};
    string s {"qqq"};
    int j {0};
    X2() = default;        // all members are initialized to their defaults
    X2(int ii) :i{ii} {}   // s and j initialized to their defaults
    // ...
};
X2 x{111};
cout << x.i << ", " << x.s << ", " << x.j;

111, qqq, 0

其他选项

我们也可以通过设定构造函数的默认参数来明确默认的初始值。这在老代码中比较常见。但是这样做,会导致传递的参数过多,而且如果要增加一个新的构造函数,还要重复这些参数列表。

class X3 {   // BAD: inexplicit, argument passing overhead
public:
    int i;
    string s;
    int j;
//public:
    X3(int ii = 666, const string& ss = "qqq", int jj = 0)
        :i{ii}, s{ss}, j{jj} { }   // all members are initialized to their defaults
    // ...
};
X3 x{};
cout << x.i;
666

强化

  • (简单)每个构造函数都要能够通过执行构造函数体或者默认构造函数,初始化所有的成员变量。
  • (简单)使用类内的成员变量初始值比构造函数的默认参数更好。