16章 コピーコンストラクタ

http://www.geocities.jp/ky_webid/cpp/language/016.html

またまたややこしそうなものが出てきました。C++は新しい概念が沢山ありますね。C言語でも割と結構いっぱいいっぱいだったので先が思いやられます。

とにかく良く読んでいったいどういうものなのかを理解したいと思います。

CSample obj2 = obj1;  // obj1を使って初期化

すると、このときコピーコンストラクタが呼び出されます。この場合、obj1をコピーしてobj2を作ったことになります。

なぜ、コピーコンストラクタが存在するかというと、上のように初期化しようとすると、実際には2度初期化されることになるからです。まず、obj2が宣言されたのでobj2のコンストラクタが呼び出され、更にobj1の値を使って初期化されます。どうせ、obj1の値を使って初期化するのであれば、最初のコンストラクタ呼び出しは無駄になります。そこで、上のような初期化を行う場合には、コピーコンストラクタが1回呼び出されるだけで済むようにしています。

なるほど。なんだか後付で無理やりとってつけたような仕様っぽい感じもしますが良しとしましょう。

この手の問題が出るケースは関数の引数としてオブジェクトを値渡しした場合とかだと思うのですが、そもそもオブジェクトみたいな複雑なデータ構造のものをポインタや参照を使わずに値渡しをすること自体殆どにおいて間違えてるような気はします。

ですが、それでもどうしても値渡ししたい場合の救済処置としてのコピーコンストラクタなんでしょう。きっと。

デストラクタでメンバ変数が確保しているメモリの解放とかが問題になるのは、結局のところ値渡ししてるのが悪いと個人的には思いました。

とりあえずコピーコンストラクタの実装をしてみます。

#include <iostream>

class CClass {
public:
    CClass(); // 通常のコンストラクタ
    CClass(const CClass& obj); // コピーコンストラクタ
};

CClass::CClass () {
    std::cout << "通常のコンストラクタ" << std::endl;
}

CClass::CClass (const CClass& obj) {
    std::cout << "コピーコンストラクタ" << std::endl;
}

void func(CClass obj) {
    
}

int main () {
    CClass obj;
    
    func(obj);
    
    return 0;
}
$ main
通常のコンストラクタ
コピーコンストラクタ

確かにfunc呼び出しの時点でコピーコンストラクタが呼ばれていますね。

とにかく今はこういう機能があるということだけ認識しておきます。

基本的には参照、およびポインタを使って実装していきたいと思います。