C++には参照が2種類あって、それが左辺値参照T&右辺値参照T&&
本当は怖くないムーブセマンティクス - yohhoyの日記(別館)
参照宣言 - cppreference.com

右辺値参照とは

  • 一時オブジェクトの生存期間を延長するもの
  • std::moveを使って作り出すことが多い?
  • T&&を受け取る関数を呼び出すためのものだと思っている
    • つまりnew T(other)だとコピーコンストラクタが呼ばれるが、new T(std::move(other))だとムーブコンストラクタが呼ばれる、みたいな使い分けをするためだけの存在
    • 少なくとも仕様に沿った説明ではなさそうだが……
  • T&& xがあったとき、x という式はT&として評価される
    • 初見だとかなり直感に反するが、T::T(U&& x): a_(std::move(x.a)), b_(std::move(x.b)) {} のようなコードを考えると納得
      • x.aの時点でmoveされるとx.bを参照したいときにこまります
  • 参照なので参照元が別途必要
    • std::vector<T> v の要素を T&& e に入れてから v.pop_back() したのち std::move(e) とかやっても駄目(1敗)
  • 例えばstd::vectorを受け取ってすべての値を2倍にした新しいvectorを返す、みたいな関数は以下のようになる(参考サイトより):
    •   typedef std::vector<int> IntVec;
        IntVec twice_vector(IntVec a)
        {
          for (auto& e : a)
        	e *= 2;
          return std::move(a);
        }
        
        IntVec v = { /*...*/ };
        IntVec w = twice_vector( std::move(v) );
      • こうすると、引数aはコピーコンストラクタではなくムーブコンストラクタによって構築されるのでパフォーマンスが良くなるということ?
      • 呼び出し元がstd::moveを使わなかったらコピーになってしまうが、仕方ないということなんだろうか
        • 逆にIntVec&&を受け取る関数にすると、std::moveを使わずに呼び出すことができなくなるので不便、という説明が記事にある
      • return std::move(a) においてstd::moveは不要である可能性がある
        • コンパイラはこういうときに暗黙のムーブをすることがあるらしい?ため
          • implicit behaviorやめてね~