2015-01-05 6 views
10

メモリを管理するクラスがあり、ユーザ定義の特別なメンバ関数が必要です(想像するとvectorなど)。それは有効移動-代入演算子を実装するために、このようデストラクタとムーブコンストラクタによるムーブ代入の実装

Class& operator=(Class&& rhs) 
{ 
    this->~Class();     // call destructor 
    new (this) Class(std::move(rhs)); // call move constructor in-place 
} 
  1. です:

    は移動-代入演算子の次の実装を考えてみましょうか?つまり、この方法でデストラクタとコンストラクタを呼び出すのは、言語のオブジェクトライフタイム規則に反しないでしょうか?

  2. これは良い考えですこの方法で移動代入演算子を実装するには?そうでない場合は、どうすればよいでしょうか、より良い標準的な方法がありますか?

+3

'〜クラス'または 'new(this)クラス(std :: move(rhs))'がスローするとどうなりますか? – Yakk

答えて

6

有効ではありません:この移動割り当てが子オブジェクトの移動の一部として呼び出された場合はどうなりますか?次に、子を破棄して(仮想デストラクタを持っていると仮定して)、その場所に親オブジェクトを再作成します。

私は非仮想的な文脈であっても、構文が頻繁に見えず、将来のメンテナーのためにコードを難しくするかもしれないので、やはり悪い考えです。

ベスト・アプローチは、すべてのクラス・メンバーが自分自身を移動させるようにすることによって、独自の移動コンストラクターを完全に(そしてデフォルトを使用して)記述する必要を回避することです。例えば、unique_ptrなどに頼ってください。スワップ(コピーアサインのためのコピーアンドスワップ)の観点からそれを実装することは、わかりやすい仕組みになるとは思えません。

2
  1. 有効である可能性があります(1)。 dtor/ctorの存続期間に関するあなたの特定の問題に対処するために、有効です(2)。これは、ベクターの元の実装がどのように機能したかです。
  2. それは(それはおそらくない)良いアイデアかもしれないが、あなたは、標準的な方法を望んでいないことがあります。(3)

(1)動きがで有効にする必要があるかどうかについての論争があります自己移動の場合。 自己移動の安全についての疑問は、コードが安全でなければならないという位置です(確かに、自己割り当てが安全であると確信しています)。また、いくつかのユーザーエクスペリエンスでは、移動、自己移動を使用する多くのアルゴリズムではチェックが可能で退屈であることが報告されています。

自己移動の安全性に対する疑念は、移動意味の全体が時間節約であり、そのためにできるだけ速く動くべき位置です。自己移動チェックは、移動コストに比べて高価になる可能性があります。自然な(キャストされていない)右辺値は自己移動できないため、コンパイラは自己移動コードを生成しません。自己移動を行う唯一の方法は、 "std :: move()"キャストを明示的に呼び出す場合です。これは、std :: move()の呼び出し元に負担をかけることで、自己移動が関与していないかどうかを検証したり、自己移動が関与していないことを確かめたりします。また、 "std :: move"に相当するユーザー定義のセルフ・ムーブをチェックしてから、何もしなかったことは自明です。自己移動をサポートしていない場合は、それを記録することができます。

(2)これはテンプレートではないので、 "new(this)Class(s​​td :: move(rhs));"投げることができます。可能であれば、これは無効です。

(3)このコードは、より伝統的なスワップアプローチを期待するかもしれないメンテナのパズルかもしれませんが、スワップアプローチの潜在的な欠点があります。ターゲットによって解放されるリソースができるだけ早く解放される必要がある場合(ミューテックスなど)、スワップにはリソースが移動元オブジェクトにスワップされるという欠点があります。移動が "std :: move()"の呼び出しの結果である場合、移動元オブジェクトはすぐに処理されないことがあります。 (これはテンプレートではないため、どのリソースが解放されているか知ることができます。メモリが唯一のリソースであれば問題ありません)

より良いアプローチは、リソースの解放デストラクタのコードと移動コンストラクタのリソース移動コードを使用して、この移動代入演算子でそれらの(インライン化された)ルーチンを呼び出します。

関連する問題