C++ のクラスの基礎
デフォルトコンストラクタ、デストラクタ
コピーコンストラクタ、コピー代入演算子
ムーブコンストラクタ、ムーブ代入演算子
本記事の前提条件は以下の通りです。
- 初心者向け
- とは言っても、何らかのプログラムはそれなりに書けるけど、C とか C++ はちょっと、という人向け
- ざっくり概要しか説明しないので細かいことは気にしないでいただきたい
- Visual Studio 2013 くらい~
- Windowsプログラム (CUI, GUI)
- コードの検証
- 開発環境: Visual Studio 2022, x64, Release ビルド
- 実行環境: Windows 10
- 本記事は上から順番に読む前提となっている
- 「Windowsプログラム (CUI, GUI)」と書いてあるが、本記事の内容だとどの OS でもほぼ同じ
前提知識として必要と思われる情報
ムーブコンストラクタとムーブ代入演算子については、コンパイラのバージョンによっていろいろと挙動が変わっているので注意が必要。
あと、ムーブコンストラクタとムーブ代入演算子については、本記事では特に詳細な説明はしないのであしからず。
特殊メンバ関数
例えばこんなクラスを作ったとする。
class DoNothing
{
};
普通に使うことはできる(なにも起こらないので意味はないが...)。
DoNothing doNothing;
DoNothing doNothing2 = doNothing;
実はこの時、コンパイラはいくつかのメンバ関数を勝手に作っている(かもしれない)。
対象となるメンバ関数は以下の通り。
- デフォルトコンストラクタ
- デストラクタ
- コピーコンストラクタ
- コピー代入演算子
- ムーブコンストラクタ
- ムーブ代入演算子
// デフォルトコンストラクタ
DoNothing();
// デストラクタ
~DoNothing();
// コピーコンストラクタ
DoNothing(const DoNothing& src);
// コピー代入演算子
DoNothing& operator=(const DoNothing& src);
// ムーブコンストラクタ
DoNothing(DoNothing&& src) noexcept;
// ムーブ代入演算子
DoNothing& operator=(DoNothing&& src) noexcept;
これらがないと、上記のプログラムは動かない。というかそもそもコンパイルできない。
ムーブコンストラクタとムーブ代入演算子については、本記事ではこれ以上の説明はしないのであしからず。
デフォルトコンストラクタ
引数なしでクラスオブジェクトが構築されるときに呼ばれる。
したがって、
DoNothing doNothing;
と書いた時点でデフォルトコンストラクタが呼ばれる。
デストラクタ
クラスオブジェクトが解放されるときに呼ばれる。
したがって、
DoNothing doNothing;
のスコープが外れるときに呼ばれる。
コピーコンストラクタ
コピー初期化されるとき。
DoNothing doNothing2 = doNothing;
コピー代入演算子
代入演算子で代入されるとき。
DoNothing doNothing;
DoNothing doNothing2;
doNothing2 = doNothing;
特殊メンバ関数の暗黙的な定義について
特殊メンバ関数が暗黙的に定義されるかどうかについては、いろいろとややこしい条件がある。
例えば、コピーコンストラクタが明示的に定義されていた場合は、デフォルトコンストラクタは暗黙的には定義されない、など。
(詳細についてはここでは説明しないが、コンパイラの気持ちになってよく考えればわかるかも?)
暗黙的に定義されない場合は、明示的に定義するか、明示的なデフォルト定義を行う必要がある。
// 明示的な定義の例
class DoNothing
{
public:
DoNothing()
{
// オブジェクトの初期化に必要な処理
}
~DoNothing()
{
// オブジェクトの解放に必要な処理
}
DoNothing(const DoNothing& src)
{
// オブジェクトのコピーに必要な処理
}
DoNothing& operator=(const DoNothing& src)
{
// オブジェクトのコピーに必要な処理
}
};
// 明示的なデフォルト定義の例
class DoNothing
{
public:
DoNothing() = default;
~DoNothing() = default;
DoNothing(const DoNothing& src) = default;
DoNothing& operator=(const DoNothing& src) = default;
};
以上。