4

コンパイラが次のsetterメソッドでwstringのmoveコンストラクタを自動的に使用できるかどうかを知りたい(std :: moveを明示的に呼び出さないで):

void SetString(std::wstring str)
{
    m_str = str;  // Will str be moved into m_str automatically or is std::move(str) needed?
}

私が読んだところによると、strは左辺値であるため、コンパイラーはこの決定を行うことが許可されていないように聞こえますが、ここでmoveを使用してもプログラムの動作は変わらないことは明らかです。

移動を除いて、他の種類のコピーの省略が適用されますか?

4

3 に答える 3

3

[is]コンパイラ[...]moveコンストラクタを自動的に使用することを許可

はい、いいですね。しかし、これは最適化であるだけでなく、言語に実際の影響を及ぼします。

次のような移動専用タイプを考えてみましょうunique_ptr

std::unique_ptr<int> f()
{
  std::unique_ptr<int> up;
  return up; // this is ok although unique_ptr is non-copyable.
}

あなたのルールが「引数の最後の出現」のルールと呼ばれるC++標準に含まれると仮定しましょう。

void SetString(std::unique_ptr<int> data)
{
    m_data = data; // this must be ok because this is "argument's last occurence"
}

返品に識別子が使用されているかどうかを確認するのは簡単です。それが「引数の最後の出現」であるかどうかをチェックすることはそうではありません。

void SetString(std::unique_ptr<int> data)
{
    if (condition) {
      m_data = data; // this is argument's last occurence
    } else {
      data.foo();
      m_data = data; // this is argument's last occurence too
    }
    // many lines of code without access to data
}

これも有効なコードです。したがって、各コンパイラは「引数の最後の出現」をチェックする必要がありますが、これは簡単なことではありません。そのためには、最初の行が有効かどうかを判断するために、関数全体をスキャンする必要があります。これを確認するために2ページ下にスクロールしなければならない場合、人間として推論することも困難です。

いいえ、C++11ではコンパイラは許可されていません。また、この機能は一般にコンパイラーで実装するのが非常に困難であり、ユーザーにとって便利であるため、将来の標準ではおそらく許可されません。

于 2013-03-21T19:13:12.110 に答える
1

いいえ、コンパイラは許可されていません。難しいだけでなく、いくつかの理由で。コピーと移動には副作用があると思います。それぞれがいつ使用されるかを知る必要があります。たとえば、ローカルオブジェクトを返すと移動することはよく知られています。文書化されていれば、問題はありません。

したがって、次の可能性があります。

あなたの例:

void SetString(std::wstring str)
{
     m_str = str;  
}

r値の場合:の1つのr-refとstr、のコピーm_str。l値の場合:のstrコピーm_str

手動で「より良く」行うことができます。

void SetString( std::wstring str)
{
     m_str = std::move(str);  
}

r値の場合:の1つのr-refとstr、への移動m_str。l値の場合:str移動中のコピーm_str

何らかの理由で(変更なしでC ++ 11なしでコンパイルしたいが、コードを移植するときにC ++ 11を自動的に利用したい場合)、実行できるコードを「手動で最適化」したくない場合:

void SetString(const std::wstring& str)
{
     m_str = str;  
}

r値の場合:の1つの参照とstr、のコピーm_str。l値の場合:strコピー内の参照m_str。決して2コピーしないでください。

于 2013-03-21T19:14:46.010 に答える
1

いいえ、ここでは移動セマンティクスは使用されません。これは、次のコードでstrを使用できるためです。実際、右辺値であっても、std :: moveを強制する必要があります。移動セマンティクスを使用する場合は、次のようにすることをお勧めします。 wstring && strを関数に移動し、moveを使用します。

于 2013-03-21T18:41:28.513 に答える