CppCoreGuidelines C.48 对于初始化为常量的成员,用类内成员初始化方法
17 October 2022
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
强化
- (简单)每个构造函数都要能够通过执行构造函数体或者默认构造函数,初始化所有的成员变量。
- (简单)使用类内的成员变量初始值比构造函数的默认参数更好。