Visualization Tool Kit(VTK)など

クラスがポインタをメンバーとして持つ場合に、破棄されるオブジェクトの内容をコピーするのではなく、移動させれば効率がよい。
それを可能とするのが右辺値参照である。

引数を右辺値参照でうける場合は && をつける。

Sample1 Move Constructor/ Assignment, ただしdouble* SomeClass::data
  SomeClass::SomeClass( SomeClass&& src ) : data(nullptr)
  {
    data = src.data; //コピーせずにポインタをもらう。
    src.data = nullptr; // ポインタはもらったのでdeleteせずにnullptrにしておく
  }

  SomeClass& SomeClass::operator=( SomeClass&& src ) 
  {
    if( this != &src)
    {
      delete data; 
      data = src.data; //コピーせずにポインタをもらう。
      src.data = nullptr; // ポインタはもらったのでdeleteせずにnullptrにしておく
    }
  }
  

Sample1 std::moveによる強制的な移動
template<typename Ty>
void Swap( Ty& a, Ty& b)
{
  //Ty tmp = a; //これだとコピーが発生する
  Ty tmp = std::move(a); //Tyのmove constructorが呼ばれる。
  a = std::move(b); //Tyのmove assignment( Ty::operator(Ty&& b) )が呼ばれる
  b = std::move(tmp); //同上。tmpの中身をbに移動させる。tmpの中身はなくなる
}

特に値型の返り値をもつクラスについてはコピーのコストを大きく削減することができる。

例えば以下のようなグローバル関数を持つクラス。
class Matrix;
Matrix RotationMatrixX(double radian)
{
  Matrix m;
  //foo
  return m;
}

RotationalMatrixXの返り値をコピーするのは無駄であるが、返り値 m はRotationalMatrixXのローカル変数であるから、返り値を参照するわけにはいかない。
このような場合、返り値mを右辺値といい、move constructor、move assginmentがあればそちらを使う。
とりあえずは、move constructorとmove assignmentを定義・実装しておけば、引数が右辺値の場合はそちらが呼ばれるようになる。


SomeClass MakeSomeClass();

int main()
{
  SomeClass a, b;
  a = b; //copy assignment
  SomeClass c( a ); // copy constructor
  SomeClass d( MakeSomeClass() ); // move constructor
  a = MakeSomeClass(); // move assignment
}

コメントをかく


「http://」を含む投稿は禁止されています。

利用規約をご確認のうえご記入下さい

Menu

メニュー

チュートリアル

アルゴリズム(数学)

並列計算

STL

#include<memory> #include<string> #include<sstream> #include<algorithm> #include<functional> #include<numeric>

Media Foundation

【メニュー編集】
Wiki記法ガイド

メンバーのみ編集できます