はじめに
Effective C++ 第3版の4項19ページから勉強していきます。
今回は、「クラスのメンバ変数の初期化」についです。
Effective C++ 第3版 - 4項 オブジェクトは、使う前に初期化しよう -
クラスのメンバ変数の初期化
初期化と代入
以下のコードのようなPersonクラスを考えます。
class Person {
public:
explicit Person(const std::string &name, const int &age);
explicit Person();
private:
std::string name_;
int age_;
};
このクラスのコンストラクタを定義します。
Person::Person(const std::string &name, const int &age) {
name_ = name; // 代入であって初期化でない
age_ = age; // 代入であって初期化でない
}
上のコードのように書けば、コンストラクタで初期化することができます。
しかし、これはベストな方法ではありません。
C++では、コンストラクタが実行される前に、データメンバが初期化されることになっています。
そのため、上のコードでは、デフォルトコンストラクタが呼ばれた後に、代入を行っています。
ただし、組み込み型(int 等)は、代入の前に初期化されている保証はありません。
一般に、コンストラクタでは、メンバ初期化リストを使って、メンバ変数を初期化したほうが良い。
メンバ初期化リストを使った初期化の仕方は、以下のコードです。
Person::Person(const std::string &name, const int &age)
: name_(name),
age_(age)
{}
上のコードは、先ほど、定義したコンストラクタと同様の結果となるが、
デフォルトコンストラクタが呼ばれた後に、代入するといった無駄な処理を省くことができる。
つまり、メンバ変数 name_ は、name を引数にしてコピーコンストラクタで初期化されることになる。
デフォルトコンストラクタで初期化するメンバ変数に対しても、初期化子を用いて、初期化ができます。
そのコードは、以下のようになります。
Person::Person()
: name_(), // デフォルトコンストラクタを呼び出す
age_(0) // ここでは明示的に0で初期化
{}
ユーザー定義型のデータメンバは、初期化子で初期化しなければ、自動的にコンパイラがデフォルトコンストラクタが呼び出します。
そのため、上のようなコードをやりすぎ(無駄)と考えるプログラマもいるそうです。。
私は、メンバ変数の数が少なければ、すべて初期化子リストで初期化していました。
また、メンバ変数の数が多すぎると、初期化子リストを使わず、代入で済ましていました。
以下に、勉強で使用したコードを示します。
サンプルコード
# include <iostream>
/*
Person::Person(const std::string &name, const int &age) {
name_ = name; // これらは代入であって初期化ではない
age_ = age;
}
*/
// は、コンストラクタの本体が実行される前に、データメンバが初期化され、その後に代入している。
// 一般に、classの初期化には、代入ではなく、メンバ初期化子リストを使う
// Person::Person(const std::string &name, const int &age) : name_(name), age_(age) {}
// のように書くと、一度初期化された後に、代入する無駄を省くことができる。
class Person {
public:
explicit Person(const std::string &name, const int &age);
explicit Person();
private:
std::string name_;
int age_;
};
/*Person::Person(const std::string &name, const int &age) {
name_ = name; // これらは代入であって初期化ではない
age_ = age;
}*/
Person::Person(const std::string &name, const int &age) : name_(name), age_(age) {}
Person::Person() : name_(), age_(0) {}
int main(int argc, char *argv[]) {
std::cout << "4_initialize_class.cpp" << std::endl;
Person per("Mike", 25);
}
実行結果
参考文献
・https://www.amazon.co.jp/gp/product/4621066099/ref=dbs_a_def_rwt_hsch_vapi_taft_p1_i0