5

次の「最小限の」例では、3 (半分) のルールの使用を示します。

#include <algorithm>
#include <iostream>

class C
{
    std::string* str;
public:
    C()
        : str(new std::string("default constructed"))
    {
        std::cout << "std ctor called" << std::endl;
    }
    C(std::string* _str)
        : str(_str) 
    {
        std::cout << "string ctor called, "
            << "address:" << str << std::endl;
    }
    // copy ctor: does a hard copy of the string
    C(const C& other)
        : str(new std::string(*(other.str)))
    {
        std::cout << "copy ctor called" << std::endl;
    }

    friend void swap(C& c1, C& c2) {
        using std::swap;
        swap(c1.str, c2.str); 
    }

    const C& operator=(C src) // rule of 3.5
    {
        using std::swap;
        swap(*this, src);
        std::cout << "operator= called" << std::endl;
        return *this;
    }

    C get_new() {
        return C(str);
    }
    void print_address() { std::cout << str << std::endl; }
};

int main()
{
    C a, b;
    a = b.get_new();
    a.print_address();
    return 0;
}

次のようにコンパイルしました (g++ バージョン: 4.7.1):

g++ -Wall test.cpp -o test

さて、どうすればいいでしょうか?a = b.get_new();この行がハードコピーを作成する、つまり新しい文字列を割り当てると仮定しました。理由:operator=()は、この設計パターンで典型的な値ごとに引数を取り、ディープ コピーを作成するコピー ctor を呼び出します。本当に何が起こったのですか?

std ctor called
std ctor called
string ctor called, address:0x433d0b0
operator= called
0x433d0b0

コピー ctor が呼び出されることはなかったため、コピーはソフトでした。つまり、両方のポインターが同じでした。copy ctor が呼び出されないのはなぜですか?

4

3 に答える 3