Hatena::ブログ(Diary)

joynote break;

2011-12-14

[][] move semanticsについて

人/後輩に教える時用の脳内カンペ。

ムーブセマンティクス(move semantics)というのは、コピーではなく、所有権の移動をさせるように動作するような考え方のこと。

例えば、下記のコードで

MyClass a; // aというインスタンスを作成
MyClass b = a; // aの中身の所有権がbに移動(move)

というような動作をするように書く感じ。

C++11でmove semanticsがッ! という言葉面だけ見ると、C++11があたかも全く新しい概念に対応したかのように(少なくとも昔の自分には)見えてしまう。

が、moveという考え方は昔から存在し、C++03でも書くことは可能だった。

例えば、こんな感じ。

struct MyClass{
    int* value;
    MyClass():value( NULL ){}
    MyClass(int num):value( new int(num) ){}
    ~MyClass(){ delete value; }
    void Move(MyClass& temp){
        value = temp.value;
        temp.value = NULL;
    }
};
int main(){
    MyClass a(100); // aというインスタンスを作成
    MyClass b;      // bという中身が空(value==NULL)のインスタンスを作成
    b.Move(a); // aの中身の所有権がbに移動(move)
}

ああ、まぁそう書けばそうなるけどさ……というレベルの簡単なコードです、が。

この書き方は、意識的に書く必要があって、面倒くさい。

operator =とか、コピーコンストラクタでこういう動作をした方が明らかにスマート。

でも、コピーのつもりが移動(move)されてたなんて事になったら、凄まじいバグの温床になる(有る筈の物が移動してどっか行っちゃうわけなので)。

でも、不必要なコピーをムーブに置き換えられたら、早くなって素敵だよね……という訳で、速度狂のC++erは、

「じゃあ、"今後、明らかに不要"なのを判別できるようにして、それだけを移動の対象にすればよくね? そう、右辺値とか」

と考えた結果、C++11で導入された右辺値参照を引数に取るコンストラクタ/代入演算子で「移動(move)」を別途定義できるようにしたのでありました!

※右辺値とは、凄まじく簡単に語弊を恐れず言えば、通常のコード上では一時的に生成されたコピー"元"の値であり、コピー先の値にコピーが終わった段階で破棄されるもの。関数の返り値として帰ってきた値とか。


という事で、具体的なコードは↓らへん

http://d.hatena.ne.jp/joynote/20110822/1314012953

http://d.hatena.ne.jp/joynote/20110608/1307523140

C++11に対応しているコンパイラでは、標準ライブラリでもあるSTLmoveに対応しているので、std::vector<T>の中身に関しても上の方のコードのint* valueに対する処理のような感じになっており、vector内部のポインタの付け替えによって「移動(move)」が行われるようになっている。

つまり、

今までのコードを書き換えなくても早いよ!

前は意識してテクニカルに書かなきゃいけない部分が見た目簡単に書けるよ!

ということでした!

========================

厳密さを欠いている可能性は非常に高いので、ツッコミは待ってます。

スパム対策のためのダミーです。もし見えても何も入力しないでください
ゲスト


画像認証

リンク元