コピー 解答ページ | Programming Place Plus Modern C++編【言語解説】 第13章

トップページModern C++編 C++編](../../index.html) – 第13章

Modern C++編は作りかけで、更新が停止しています。代わりに、C++14 をベースにして、その他の方針についても見直しを行った、新C++編を作成しています。
Modern C++編は削除される予定です。

問題①

問題① 次のプログラムのコメント部分では何が行われているかを、コンストラクタ、コピーコンストラクタ、コピー代入演算子、デストラクタといった関数のどれが呼び出されているのかという観点から説明してください。

class MyClass {
};

MyClass func1(MyClass mc)
{
    return mc;
}

MyClass* func2(MyClass* mc)
{
    return mc;
}

MyClass& func3(MyClass& mc)
{
    return mc;
}

int main()
{
    MyClass a;       // A
    MyClass b = a;   // B
    MyClass c(b);    // C
    MyClass* d;      // D

    c = a;           // E

    c = func1(a);    // F
    d = func2(&a);   // G
    c = func3(a);    // H
}


Aは、実引数がありませんから、デフォルトコンストラクタが呼び出されます。MyClass には明示的なコンストラクタを定義していないので、コンパイラが自動的に生成したデフォルトコンストラクタが使用されます。

Bは、b と同じ型の a を初期値として与えていますから、コピーコンストラクタが呼び出されます。MyClass には明示的なコンストラクタを定義していないので、コンパイラが自動的に生成したコピーコンストラクタが使用されます。もし、コピーコンストラクタを明示的に定義しており、explicit が付いていたら、この記法はコンパイルエラーになります。

Cもコピーコンストラクタが呼び出されます。こちらは、explicit の付いたコピーコンストラクタを定義していても使用可能な構文です。

Dは、ポインタ変数の宣言なので、MyClass型のオブジェクトが作られるわけではありません。したがって、MyClass のコンストラクタが呼び出されることはありません。単に未初期化で、どこも指していないポインタ変数が定義されるだけです。

Eは、c も a も、MyClass型なので、「MyClass::operator=(const MyClass&)」のコピー代入演算子が使用されます。これは、明示的に定義していませんが、コンパイラが自動的に生成したものが使用されます。

Fは、まず引数 mc を作るために、a を使ったコピーコンストラクタが呼び出されます。戻り値も MyClass型なので、一時オブジェクトを作るために、mc を使ったコピーコンストラクタ(C++11以降ではムーブコンストラクタ)が呼び出されます。これを func1関数の呼び出し元が c に受け取ります。これは生成ではなく、代入なので、コピー代入演算子が呼び出されます。

また、この過程の中で、mc と一時オブジェクトを破棄するためのデストラクタが呼び出されます。

ただし、これらは理屈上の話で、実際には最適化によっていくつかの呼び出しは取り除かれるはずです。

Gは、func2関数の仮引数 mc は MyClass*型なので、単なるポインタ変数のやり取りです。戻り値も同様で、ポインタ変数を返すだけですから、MyClass のメンバ関数が呼び出されることはありません。

Hは、func3関数の仮引数 mc は参照なので、オブジェクトが作られることは無く、MyClass のメンバ関数が呼び出されることはありません。戻り値についても参照で返されているので、一時オブジェクトが生成されることはありませんが、受け取り側は実体の変数 c に代入しているため、コピー代入演算子は呼び出されます。


参考リンク


更新履歴

’2017/8/22 C++11 以降の動作に合わせて、コピーや一時オブジェクトに関する記述を追記・修正。

’2017/8/16 新規作成。



第13章のメインページへ

Modern C++編のトップページへ

Programming Place Plus のトップページへ



はてなブックマーク に保存 Pocket に保存 Facebook でシェア
X で ポストフォロー LINE で送る noteで書く
rss1.0 取得ボタン RSS 管理者情報 プライバシーポリシー
先頭へ戻る