2

次のクラスがあり、コンパイラにすべてのコピー/移動コンストラクターと代入演算子を強制的に生成させます。

class foo {
public:
    float *x;
    size_t size;
    foo(int m){
        size = m;
        x = new float[size];}

    foo(const foo&) = default;
    foo(foo&&) = default;
    foo& operator =(const foo&) = default;
    foo& operator =(foo&&) = default;

    ~foo(){delete [] x;}

    void fill(const float& num)
    {
        std::fill(x,x+size,num);
    }

    void print()
    {
        for (auto i=0;i<size;++i)
            cout << x[i] << endl;
        cout << endl;
    }
};

次にmain、このように関数から呼び出します

int main()
{
    foo x(2);
    x.fill(6);
    x.print();


    foo y(2);
    y = x; // causes the error

    return x;
}

これで、割り当てによってメモリを 2 回解放していることがわかりy = xます。どちらかが解放されると、もう一方はnullですよね?先に進んで、独自のコピー代入演算子を実装しました

foo& operator=(const foo& other)
{
    if (other.x!=x)
        x = other.x;
    return *this;
}

ただし、ここでも、デフォルトのコンストラクターがとにかく行っていることを行っていると思います。私の質問は、この問題が発生しないように適切なコピー代入演算子を作成する方法です。

4

1 に答える 1

1

ポインターではなく、ポインターの内容をコピーする必要があります。使用する良いアプローチは、コピーとスワップのイディオムです。これは、コピー コンストラクターが の内容をコピーする作業を既に実行している必要があるためですx

friend void swap(foo& first, foo& second)
{
    using std::swap; 
    swap(first.x, second.x); 
    swap(first.size, second.size);
}

foo& operator=(foo other) // note pass by value
{
    swap(*this, other);
    return *this;
}
于 2015-09-17T19:00:26.503 に答える