5

C++の移動セマンティクスには多くの機会を逃しているようです。これらの背後にある理論的根拠と、次の場合に変数を移動するタイミングを標準がより積極的に定義しない理由を理解したいと思います。

string f()
{
    string s;
    return s + " ";
}

これはoperator+(const string&, const char*)、ではなくoperator+(string&&, const char*)、を呼び出します。これsは、左辺値であるためだと思います。関数でのローカル変数の最後の使用では、変数は移動可能であると見なされると標準は言うことができませんでしたか?

私はやや似た例だと思います:

struct A { A(string&&); };
string g()
{
    string s;
    return s; // s is moved
}
A h()
{
    string s;
    return s; // s can't be moved!
}

g移動セマンティクスを使用してデータをからs戻り値に移動しますが、に移動されhないためコンパイルされません。これは、標準には、戻り型とまったく同じ型のローカル変数を返すと、変数が移動されるという基本的なケースがあるためだと思います。ローカル変数を返すと、そのタイプに関係なく移動されるというルールがないのはなぜですか?shg

4

2 に答える 2

6

sどちらの例でも移動が必要になる可能性があると確信していますが、最後に使用されているのが「明らか」であり、移動する必要があると考える別のケースを誰かが思いつくでしょう。

最終的には、コンパイラが実行する必要があるデータ フロー分析を定義する標準が得られます。作成者は、実装がその点でばかげていることを許容するために、控えめに線を引くことにしました。std::moveプログラマーは、コピーを移動に変更するためにいつでも書き込むことができます。

もう 1 つの可能性は、オブジェクトが移動またはコピーされるかどうかが指定されていないことを標準が示すことです。これにより、実装を好きなだけ賢くすることができます。それは悪い考えだと確信しています。実際には、ユーザーは自分のオブジェクトが移動されたかどうかを気にしないことがよくありますが、時にはそれを解決する必要があります。

于 2012-11-29T16:36:22.153 に答える
2

簡単に言えば、これは現在の標準では不必要な制限であり、自動移動はコピー省略の可用性に依存します。

別の例は次のとおりです。

struct X{
  std::string s;
};

std::string foo(){
  X x;
  return x.s; // no automatic move
};

http://isocpp.orgの Future Standard Proposals フォーラムでスレッドを開きました。ここで見ることができます。リチャード・スミスの助言を受けて、私はマイク・ミラーに直接メールを送り、これに関する核となる問題を提起したところ、次のような回答を得ました。

[...] 上記のリチャードの要約に基づいて、それは合理的な質問のように聞こえるので、問題リストの次の改訂で問題を開きます。ありがとう。

したがって、C++14 の場合、これらの制限はすべてなくなり、ローカル変数が返されるたびに自動的に移動します。

リチャードの要約は次のとおりです。

より具体的には、[class.copy]p31 には、"return id-expression;" というステートメントに対してコピーを省略できるという規則があります。ここで、id-expression はローカル変数を指定し、変数は関数の戻り値の型と同じ cv 修飾されていない型を持ちます。提案は、「return id-expression;」ステートメントがあるときはいつでも自動移動を実行する必要があるということです。ここで、id-expression は、変数の型に関係なく、ローカル変数または関数パラメーターを指定します。

于 2012-11-29T16:50:59.230 に答える