3

これは少し理論的な質問ですが、std::move の基本的な理解はある程度していますが、理論的には超スマート コンパイラでは実現できなかった追加機能が言語に提供されるかどうかはまだわかりません。私は次のようなコードを知っています:

{
  std::string s1="STL";
  std::string s2(std::move(s1));
  std::cout << s1 <<std::endl;
} 

パフォーマンス シュガーだけでなく、新しいセマンティック動作です。:Dしかし、std::move(x)を実行した後、誰もvar xを使用しないと思います。また、可動のみのデータ (std::unique_ptr<>、std::thread) の場合、型が可動と宣言されている場合、コンパイラは古い変数の移動構築とクリアを自動的に行うことができませんでしたか? 繰り返しますが、これは、プログラマーの背後でより多くのコードが生成されることを意味します (たとえば、automagic std::moving を使用すると、cpyctor と movector の呼び出しを数えることができます)。

4

3 に答える 3

7

いいえ。

しかし、 std::move(x) を実行した後、誰も var x を使用しないと思います

絶対に保証されません。実際、コンパイラが自動的に使用できない理由のかなりの部分は、std::move(x)これを意図しているかどうかを自動的に判断できないためです。それは明示的に明確に定義された動作です。

また、右辺値参照を削除すると、コンパイラーがすべての移動コンストラクターを自動的に作成できることを意味します。これは間違いなく真実ではありません。D にも同様のスキームがありますが、これは完全な失敗です。コンパイラによって生成された「移動コンストラクター」が正しく機能せず、それを変更できないという有用な状況が多数あるためです。

また、他の用途がある完全な転送を防ぐことにもなります。

委員会は多くのばかげた間違いを犯しますが、右辺値参照はその 1 つではありません。

編集:

次のようなことを考えてみましょう:

int main() {
    std::unique_ptr<int> x = make_unique<int>();
    some_func_that_takes_ownership(x);
    int input = 0;
    std::cin >> input;
    if (input == 0)
        some_other_func(x);
}

ああ。それで?コンパイル時に「入力」の値がわかるように魔法をかけることはできません。と の本体が不明な場合、これは 2 重に問題にsome_other_funcなります。これは停止問題です。 が使用されているか使用されていないかをsome_func_that_takes_ownership証明することはできません。xsome_func_that_takes_ownership

D は失敗します。私は例を約束しました。基本的に、D では、「移動」は「バイナリ コピーであり、古いものを破壊しない」ことです。残念ながら、たとえば、それ自体へのポインターを持つクラスを考えてみましょう。これは、ほとんどの文字列クラス、ほとんどのノードベースのコンテナー、std::functionboost::variant、および他の多くの同様の便利な値型の設計に見られるものです。内部バッファへのポインタはコピーされますが、いやいや!新しいバッファではなく、古いバッファを指します。古いバッファの割り当てが解除されました - プログラムに GG を追加してください。

于 2012-08-24T14:11:37.307 に答える