25

operator=が正しく定義されている場合、コピーコンストラクタとして以下を使用しても大丈夫ですか?

MyClass::MyClass(MyClass const &_copy)
{
    *this = _copy;
}
4

8 に答える 8

30

のすべてのメンバーがMyClass既定のコンストラクターを持っている場合は、はい。

通常は逆であることに注意してください。

class MyClass
{
public:
    MyClass(MyClass const&);     // Implemented
    void swap(MyClass&) throw(); // Implemented
    MyClass& operator=(MyClass rhs) { rhs.swap(*this); return *this; }
};

operator=コピー コンストラクターが呼び出されるように値渡しします。swapはスローしないことが保証されているため、すべてが例外セーフであることに注意してください (実装でこれを確認する必要があります)。

要求に応じて、値による呼び出しについて編集します。次のoperator=ように記述できます。

MyClass& MyClass::operator=(MyClass const& rhs)
{
    MyClass tmp(rhs);
    tmp.swap(*this);
    return *this;
}

C++ の学生は通常、クラス インスタンスを参照渡しするように指示されます。これは、クラス インスタンスが値渡しされるとコピー コンストラクターが呼び出されるためです。この場合、rhsとにかくコピーする必要があるため、値渡しは問題ありません。

したがって、operator=(最初のバージョン、値による呼び出し)は次のようになります。

  • のコピーを作成しますrhs(コピー コンストラクターを介して、自動的に呼び出されます)
  • その内容を*this
  • return*thisおよび let rhs(古い値を含む) は、メソッドの終了時に破棄されます。

さて、この値による呼び出しには追加のボーナスがあります。渡されるオブジェクトoperator=(または引数を値で取得する任意の関数) が一時オブジェクトである場合、コンパイラはコピーをまったく作成できません (通常は作成します)。これはコピー省略と呼ばれます。

したがって、rhsが一時的な場合、コピーは作成されません。残っているのは次のとおりです。

  • スワップthisrhsコンテンツ
  • 破壊rhs

したがって、この場合、値渡しは参照渡しよりも効率的です。

于 2010-09-06T14:12:37.443 に答える
11

例外セーフ コピー コンストラクターに関して operator= を実装することをお勧めします。この手法の説明と、それが良いアイデアである理由については、Herb Sutter の例 4. を参照してください。

http://www.gotw.ca/gotw/059.htm

于 2010-09-06T14:14:53.960 に答える
5

この実装は、割り当てを行う前に最初に呼び出されるため、すべてのデータ メンバー (および基本クラス) の既定のコンストラクターが MyClass から使用可能であり、アクセスできることを意味します。この場合でも、コンストラクターに対してこの余分な呼び出しを行うと、コストが高くなる可能性があります (クラスの内容によって異なります)。

たとえそれがより多くのコードを書くことを意味するとしても、初期化リストを介してコピーコンストラクターの個別の実装に固執します。

別のこと: この実装には副作用がある可能性があります (たとえば、メンバーを動的に割り当てた場合)。

于 2010-09-06T14:12:52.203 に答える
1

最終結果は同じですが、メンバーは最初にデフォルトで初期化され、その後のみコピーされます。

'高価な'メンバーを使用すると、初期化子リストを使用してコピーを作成する方が適切です。

struct C {
   ExpensiveType member;

   C( const C& other ): member(other.member) {}
};



 };
于 2010-09-06T14:34:56.457 に答える
0

はい。

個人的には、equal演算子をオーバーロードしたり、コピーコンストラクターを記述したりしてコンパイラーに任せたりしないのに、クラスにポインターがない場合。シャローコピーが実装され、すべてのメンバーデータがコピーされていることが確実にわかりますが、=opをオーバーロードすると; 次に、データメンバーを追加してから、問題が発生するオーバーロードの更新を忘れます。

于 2010-09-06T14:39:01.803 に答える
0

作業代入演算子 (コピー演算子) があれば、技術的には問題ありません。

ただし、次の理由により、コピー アンド スワップを優先する必要があります。

  • コピースワップを使用すると、例外の安全性が簡単になります
  • 懸念事項の最も論理的な分離:
    • copy-ctor は、(他のものをコピーするために) 必要なリソースを割り当てることです。
    • スワップ機能は、(ほとんど)内部の「ハンドル」の交換のみを目的としており、リソースの割り当て (解放) を行う必要はありません。
    • デストラクタはリソースの解放に関するものです
    • コピーアンドスワップは、代入/コピー演算子でこれら 3 つの機能を自然に組み合わせます。
于 2011-10-05T11:19:34.667 に答える
0

MyClassがメモリを割り当てているか、変更可能である 場合、これは問題ないと思います。

于 2010-09-06T14:14:01.220 に答える
0

@Alexandre - 代入演算子での値渡しについてはわかりません。そこでコピーコンストラクターを呼び出すことで得られる利点は何ですか? これは代入演算子を固定するつもりですか?

PS コメントの書き方がわかりません。それとも、コメントを書くことを許可されていないのかもしれません。

于 2010-09-06T16:28:31.300 に答える