13

移動代入に関する標準ライブラリ ポリシーでは、自己代入が決して起こらないことを実装が想定できるようになっています。次のことを考えると、これは本当に悪い考えのように思えます。

  • C++ の「通常の」(「コピー」) 割り当てコントラクトは、常に自己割り当てに対して安全であると見なされてきました。ここで、覚えて説明しなければならない C++ の一貫性のないコーナー ケースがさらに 1 つあります。また、微妙に危険なケースもあります。C++ に必要なのは、これ以上隠された罠ではないということは、私たち全員が同意していると思います。
  • それはアルゴリズムを複雑にします -remove_ifファミリ内のすべてがこのコーナー ケースを処理する必要があります。
  • この要件を満たすのは非常に簡単です-スワップを使用して移動を実装する場合は無料で提供され、他の場合(アドホックロジックでパフォーマンスを向上させることができる場合)でも、(ほとんど)一度も使用されませんブランチは、どの CPU¹ でも事実上無料です。また、最も興味深いケース (パラメーターまたはローカルを含む移動) では、インライン化時にオプティマイザーによってブランチが完全に削除されます (これは、「単純な」移動代入演算子の場合、ほぼ常に発生するはずです)。

では、なぜそのような決定を下すのでしょうか。


¹ 特にライブラリ コードでは、実装者が「ブランチの期待される結果」に関するコンパイラ固有のヒントを自由に利用できます ( VC++__builtin_expectの gcc/で考えてください)。__assume

4

2 に答える 2

5

移動されたオブジェクトは、std再利用される前に破棄または割り当てられることになっています。 それを超えて完全に無料ではないものは約束されていません

時々物事は無料です。move-constructed-from コンテナが空であるように。一部の実装では、バッファの代わりに要素を移動することを選択する場合があるため、move-assiged-from の場合にはそのような保証がないことに注意してください。違いはなぜですか?1 つは無料の追加保証でしたが、もう 1 つはそうではありませんでした。

分岐またはその他の小切手は完全に無料ではありません。分岐予測スロットを占有し、予測されたとしてもほとんど無料です。

その上a = std::move(a);、論理エラーの証拠です。assign-from a(within std) は、 assign-to または discard のみを意味しますa。しかし、ここでは、次の行に特定の状態を持たせたいと考えています。自分が自己割り当てであることを知っているか、知らないかのどちらかです。そうしないと、オブジェクトから移動しており、それを認識していません。

「物事を安全に保つためにささいなことをする」という原則は、「使用しないものにはお金を払わない」という原則と衝突します。この場合、2番目が勝ちました。

于 2016-10-04T12:29:54.300 に答える