天天看點

C++核心準則C.48:如果構造函數需要用常數初始化成員,使用類内初始化器更合适

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

C.48:如果構造函數需要用常數初始化成員,使用類内初始化器更合适

Reason(原因)

Makes it explicit that the same value is expected to be used in all constructors. Avoids repetition. Avoids maintenance problems. It leads to the shortest and most efficient code.

明确表示希望所有的構造函數都使用相同的值。避免維護問題。可以生成最短,最高效的代碼。

Example, bad(反面示例)

class X {   // BAD
    int i;
    string s;
    int j;
public:
    X() :i{666}, s{"qqq"} { }   // j is uninitialized
    X(int ii) :i{ii} {}         // s is "" and j is uninitialized
    // ...
};      

How would a maintainer know whether j was deliberately uninitialized (probably a poor idea anyway) and whether it was intentional to give s the default value ""  in one case and qqq in another (almost certainly a bug)? The problem with j (forgetting to initialize a member) often happens when a new member is added to an existing class.

維護人員怎麼才能知道 j 是否是故意沒有初始化(盡管這可能是壞主意)呢?怎麼知道一種情況将s初始化為“”,而另一種情況初始化為"qqq"是有意而為之呢(這幾乎就是一個錯誤)?關于 j 的問題(忘了初始化某個成員)經常發生在向類添加新成員的時候。

Example(示例)

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

Alternative(可選方案)

We can get part of the benefits from default arguments to constructors, and that is not uncommon in older code. However, that is less explicit, causes more arguments to be passed, and is repetitive when there is more than one constructor:

通過使用構造函數的預設參數,我們可以得到某些好處。這種情況在老代碼中可以說很常見。然而,這種做法缺乏明确性,會導緻更多的參數被傳遞,并且在多于一個構造函數存在時導緻代碼重複,很麻煩。

class X3 {   // BAD: inexplicit, argument passing overhead
    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
    // ...
};      

Enforcement(實施建議)

  • (Simple) Every constructor should initialize every member variable (either explicitly, via a delegating ctor call or via default construction).

    (簡單)所有的構造函數都應該初始化每個成員(可以明确地通過委托構造函數或預設構造函數)

  • (Simple) Default arguments to constructors suggest an in-class initializer may be more appropriate.
  • (簡單)針對構造函數的預設參數使用類内初始化器可能是更加恰當的選擇。

繼續閱讀