LoginSignup
8
3

More than 3 years have passed since last update.

勉強記録 15日目 〜クラスのメンバ変数の初期化〜 - Effective C++ 第3版 -

Posted at

 はじめに

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で初期化
  {}

ユーザー定義型のデータメンバは、初期化子で初期化しなければ、自動的にコンパイラがデフォルトコンストラクタが呼び出します。
そのため、上のようなコードをやりすぎ(無駄)と考えるプログラマもいるそうです。。

私は、メンバ変数の数が少なければ、すべて初期化子リストで初期化していました。
また、メンバ変数の数が多すぎると、初期化子リストを使わず、代入で済ましていました。

以下に、勉強で使用したコードを示します。

サンプルコード

4_initialize_class.cpp
#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

8
3
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
8
3