C++11の右参照およびstd::move

2486 ワード

たくさんの文章を読んで、今やっとC++の中の右の値とstd::moveを理解しました
 
左と右の最も重要な違いは、右が一時的な変数であることです.
C++11では、右の値の参照にも新しい構文が追加されました.
 
たとえば、次のコードがあります.
 
void testFunc(int  &i )
{
    std::cout<<"reference test func int"<<std::endl;
}
void testFunc( int &&i )
{
    std::cout<<" Right Value test func int"<<std::endl;
}
int main() { 
    int j = 0;
    testFunc(1);
     testFunc(int());
    testFunc(j);
    system("pause");
}
 
     :
Right Value test func int
Right Value test func int
reference test func int

 
 
このとき2行の出力はRight Value test func intであり、その他はreference test func intである
この2行を見てみるとtestFunc(1)では一時変数を作成し、testFunc(int())ではint()の一時変数を作成し、
コンパイラは
右の値をtestFuunc(int&&i)に合わせます.
 
右とは何か、左とは何かを知っているはずだ.
左の値を右の値、すなわちstd::moveに変換できます.
このとき上記のコードでtestFunc(std::move(j))を呼び出すとtestFunc(int&&i)という関数が呼び出されます
 
では、この右値参照とstd::moveは何の役に立つのでしょうか.
リソースの移行によるコストの削減
C++の中で、私たちが最もよく接触するリソースはメモリです.想像してみてください.string oldStringを仮定すると、newは1 Wバイトで、newString=oldStringを呼び出したとき、string&operator=(const string&other)という関数を呼び出します.
string&operator=(const string&other)では、一般的に次のような動作をします.
1.1 W(または複数)バイトの申請
2.この1 Wバイトを新しくオープンしたメモリにコピーする
 
今まで問題はありませんでしたが、oldStringがもう使われていないと確信できたらどうしますか?私たちはやはりこの1 Wメモリをもっと申請しますか??なぜoldStringのポインタを直接newStringに割り当てないのですか?どうせoldStringはもういらない.
 
これが右の意味を増やした理由です.このとき、関数を定義することができます.
string &operator=(string &&other)
{
//thisの対応する変数にotherのポインタを割り当てる
//otherのポインタをnullptrに割り当てることが重要です.そうしないと、リソースを持っている人が混乱し、元のリソースを整理することもこの関数を書く上で重要なポイントです.
}
上の偽コードのように、リソースは新しい文字列に移動されます.移動であり、コピーではないので、元のポインタなどをnullptrに割り当てることを覚えています.
 
moveでoldStringを右に変換できます
newString = std::move( oldString)
string&operator=(string&&other)が呼び出され、1 Wバイトの申請が少なくなりましたが、oldStringのリソースも移動されました.これが移動の意味の本当の意味です.