7

私は生徒に紹介するのに十分なムーブ セマンティクスを学ぼうとしています。私は非常に単純化されたベクトルまたは文字列のようなクラスを使用しており、メモリを管理し、メンバーがメッセージを出力してアクティビティを示しています。学生に見せるための簡単な例を作成しようとしています。

RVO および gcc 4.7 の他の部分の構築省略と clang は積極的にコピーおよび移動構築を排除するため、作業中の移動割り当ては簡単に確認できますが、作業中の移動構築を見たのは、gcc 4.7 で構築省略をオフにした場合だけです。 -fno-elide-constructors を使用。

明示的なコピー構築ステートメント

MyString newString(oldString);

省略が有効な場合でも、コピー コンストラクターを呼び出します。しかし、何かのような

MyString newString(oldString1 + oldString2); 

省略のため、移動コンストラクターを呼び出しません。

std::move の説明は後で行う必要があるため、明示的に std::move を使用しても単純な例にはなりません。

だから私の質問:コピー/移動コンストラクターが省略されている場合でも、移動構築を呼び出す簡単なコード例はありますか?

4

2 に答える 2

7

簡単な例は、返される関数への引数です。標準では、この場合、移動を省略することを明示的に禁止しています (可能ではありません...)。

std::vector<int> multiply( std::vector<int> input, int value ) {
   for (auto& i : input )
      i *= value;
   return input;
}

さらに、もう少し人工的ではありますが、さらに単純な例の移動構築を明示的に要求できます。

T a;
T b( std::move(a) );

うーん...さらに別のものは含まれていませんstd::move(技術的には省略できますが、ほとんどのコンパイラはおそらく省略できません):

std::vector<int> create( bool large ) {
   std::vector<int> v1 = f();
   std::vector<int> v2 = v1;       // modify both v1 and v2 somehow
   v2.resize( v2.size()/2 );
   if ( large ) {
      return v1;
   } else {
      return v2;
   }
}

オプティマイザーは、コードを次のように書き直すことでそれを回避できます。

std::vector<int> create( bool large ) {
   if ( large ) {
      std::vector<int> v1 = f();
      std::vector<int> v2 = v1;       // modify both v1 and v2 somehow
      v2.resize( v2.size()/2 );
      return v1;
   } else {
      std::vector<int> v1 = f();
      std::vector<int> v2 = v1;       // modify both v1 and v2 somehow
      v2.resize( v2.size()/2 );
      return v2;
   }
}

コンパイラが実際にそれを行うとは思えません。各コード パスでは、返されるオブジェクトが事前に認識されて作成されるため、オプティマイザーは、書き換え後に返される場所で適切なオブジェクトを見つけることができることに注意してv1くださいv2

コピー/移動を省略できる状況については、12.8/31 で説明されています。これらのカテゴリに当てはまらないコードを書くことができ、型にムーブ コンストラクターがある場合、ムーブ コンストラクターが呼び出されます。

于 2012-09-05T16:32:45.430 に答える
1

うーん、見てみましょう:

  • MyString newString(oldString) コピーです。ここで除外するものは何もありません。実際には2 つのオブジェクトになります。

  • MyString newString(oldString1 + oldString2);一時からのコピーであるため、コピーを省略でき、連結が直接インプレースで構築されます。

これは、省略不可能な移動の構築の非常に安価な例です。

MyString boo()
{
    MyString s("Hello");
    return std::move(s);   // move-construction from the local "s", never elided
}

明示的なキャストはsRVO の対象外となるため、戻り値は からムーブ構築されsます。

于 2012-09-05T16:34:19.130 に答える