1

コピー オペレーターをコピー コンストラクターにリダイレクトしたいと考えています。後者では、古い利用可能なクラスに基づいて新しいクラスをコピー/構築するための適切なロジックを実装します。

しかし、これを行う適切な方法はどうですか?これはおそらくメモリリークしていると「思います」が、ポインタを渡さずにそれを行う方法がわかりません:

MyClass& MyClass::operator=(const MyClass& a) {
    MyClass* b = new MyClass(a); 
    return *b; 
}

これでよろしいですか?そうでない場合、適切な方法は何ですか?メソッドやプロトタイプの本体を変更する必要がありますか?

ありがとうございました。

4

6 に答える 6

2

いいえ、operator=割り当てられたオブジェクトと同じになるように現在のオブジェクト属性を設定する必要があります。メソッドはヒープに新しいオブジェクトを割り当て、それを参照として返し (本質的にリークします)、オペレーターが呼び出されたオブジェクトを完全に変更せずに残します。

たとえば、 と呼ばれるメソッドを実装してCopyFrom()、渡されたオブジェクトの属性と一致するようにすべてのオブジェクトの属性を割り当て (有効期間が によって管理されるヒープ割り当てポインターをディープ コピーしますMyClass)、コピー コンストラクターと の両方から THAT を呼び出す必要がありますoperator=

    class MyClass
    {
    public:
        MyClass( const MyClass& in )
        {
            CopyFrom( in );
        }

        MyClass& operator=( const MyClass& in )
        {
            CopyFrom( in );
            return *this;
        }

    private:
        void CopyFrom( const MyClass& in )
        {
            ... copies in's attributes into self.
        }
    };
于 2013-10-31T17:43:53.940 に答える
1

MyClass 内にポインタを格納していない限り、正しいコピー代入演算子はデフォルトで生成されたものです。ただし、実装する必要がある場合は、copy-swap イディオムを使用してコピー コンストラクターの観点から記述することができます。

MyClass& MyClass::operator = (MyClass const& a) {
    MyClass temp(a); // Call the copy constructor
    using std::swap;
    swap(temp, *this);
    return *this;
}

その理由は、using std::swap引数依存のルックアップを有効にするためです。MyClass に独自の swap 関数を定義すると、それが呼び出されます。Elsestd::swapはフォールバックとして使用されます。(編集:実際には、この場合カスタムスワップを実装する必要があります。そうしないと、無限再帰が発生します。std::swap代入演算子が使用され、std::swapが呼び出され、... が呼び出されます。)

このイディオムが好まれる理由std::swapは、スローしない関数だからです。コピー コンストラクターが例外をスローした場合でも、割り当て先のオブジェクトは有効な状態のままです。

于 2013-10-31T17:38:01.390 に答える
1

原則として、コピー代入演算子はコピーを作成しないでください。むしろ、呼び出された既存のオブジェクト (割り当ての左側) にデータをコピーする必要があります。例えば:

class MyClass
{
public:
    MyClass & operator = (const MyClass & RHS)
    {
        // Copy data from RHS into 'this'
        m_value = RHS.m_value;
        return *this;
    }

private:
    int m_value;
};

この場合、独自のコピー コンストラクターを定義する必要はありません。これは、既定の (コンパイラーが提供する) コンストラクターが正常に機能するためです。あくまでもイラストですけどね。

残念ながら、既存のオブジェクトに対してコピー コンストラクターを呼び出すことはできません。コピー スワップ パターンも代替手段ですが、効率が低下する可能性があります。

于 2013-10-31T17:44:34.320 に答える
0

絶対にコピー コンストラクターで代入演算子を実装する場合は、次を使用します。

MyClass& MyClass::operator=(const MyClass& o)
{
    this->~MyClass(); // destroy current object
    new(this) MyClass(o); // use the copy constructor
    return *this;
}

これが最善の方法となる状況は考えられません(状況によっては、より良い実装方法を説明している他の回答もあります)。

MyClass何百もの int/float フィールドと、いくつかの動的に割り当てられたポインターが含まれている場合は、おそらく (ここで物事を構成しようとしているだけです) ?

ただし、クラスにベア (非スマート) ポインターを含めることはお勧めできません。そのようなクラスがある場合、代入演算子が機能しないよりもはるかに悪い問題があります。最初にリファクタリングする必要があります。そうすれば、他のすべてのバグと一緒に問題が解消されます。

于 2013-10-31T19:15:55.770 に答える