c++11の新しい特性のmoveを簡単に勉強します
2125 ワード
moveを解釈するブログをたくさん見ましたが、はっきり言えなかったので、見てください.
新しい特性の出現は既存の問題や不足点を解決するためであり,moveの出現はいくつかのシーンでの深いコピーの効率の問題を解決するためである.
この[シーン](Scene)には、次のようなものがあります.
stringクラスの簡単な定義は次のとおりです.
考えてみれば、case 1のs 3の付与構造関数は、受信したパラメータが式結果の一時オブジェクトであり、case 2のs 4が受け入れるのも関数が返す一時オブジェクト(tmpではなく、コンパイラが生成した一時オブジェクト)である
上記の場合の呼び出し賦値コンストラクション関数はいずれもnewとdeleteを実行しており、オブジェクトが大きい場合、これは時間のかかる操作であるが、newオブジェクトはスタック空間にあり、直接制御権を新しいオブジェクトに移行すればよく、deleteを先に再newする必要がなく、c++11開始クラスの定義は2つのコンストラクション関数を多くしている:コピーコンストラクション関数を移動し、割り当て構造関数を移動し、次のように定義します.
これにより、case 1およびcase 2の場合、コンパイラはデフォルトで移動コピーコンストラクタを呼び出し、このシーンで不要な深いコピーの問題を解決します.
この概念について説明します.
case 1とcase 2でこれらのコンパイラによって生成された一時オブジェクトは、カスタマイズされたオブジェクトとは異なり、変更できません.これにより、これらのオブジェクトを右値と呼び、変更できるものを左値と呼び、右値参照と左値参照の概念が多くなります.右値参照は上に移動して使用されます.右の値の参照はconst修飾を使用できません.変更するからです.
以上で終わるはずです.しかし、移動コピー(付与)コンストラクション関数を呼び出すシーンはたくさんあります.たとえば、次のようにします.
std::vector v1 = v2 ;
このようなコードは、どこでも見られますよ.もしv 2が非常に大きなオブジェクトであれば、私たちもv 2を使用する必要はありません.もちろん、深いコピーを望んでいません.それでは、モバイルコピー構造関数を呼び出すことができます.どのように呼び出すか、強制的に呼び出すか、moveが現れます.
std::vector v1 = std::move(v2) ;
moveの意味は,移動コピー(付与)構造関数を強制的に呼び出すことである.
OK、これでよくわかります.
最後に、moveの使用習慣をまとめます.
1.c++11以降、stlは移動構造関数をサポートし、moveをサポートします.
2.カスタムクラスは、自分で移動構造関数を実現するにはmoveが有効です.
3.moveを使用した後、元のオブジェクトを使用し続けることができなくなった理由は言うまでもないでしょう.
新しい特性の出現は既存の問題や不足点を解決するためであり,moveの出現はいくつかのシーンでの深いコピーの効率の問題を解決するためである.
この[シーン](Scene)には、次のようなものがあります.
stringクラスの簡単な定義は次のとおりです.
class string{
public:
//
string(const string& s){
delelte begin[];
begin = new char[s.size+1]
strcpy(begin,s.begin,s,size);
size = s.size;
}
//
...
private:
int size ;
char* begin;
};
//case 1
string s1("abc");
string s2("def");
string s3 = s1 + s2 ;
//case2
string upper(const string& src){
string tmp ;
//upper
....
return tmp;
}
string s4 = upper(s2);
考えてみれば、case 1のs 3の付与構造関数は、受信したパラメータが式結果の一時オブジェクトであり、case 2のs 4が受け入れるのも関数が返す一時オブジェクト(tmpではなく、コンパイラが生成した一時オブジェクト)である
上記の場合の呼び出し賦値コンストラクション関数はいずれもnewとdeleteを実行しており、オブジェクトが大きい場合、これは時間のかかる操作であるが、newオブジェクトはスタック空間にあり、直接制御権を新しいオブジェクトに移行すればよく、deleteを先に再newする必要がなく、c++11開始クラスの定義は2つのコンストラクション関数を多くしている:コピーコンストラクション関数を移動し、割り当て構造関数を移動し、次のように定義します.
class string{
public:
//
string(string&& s){
delelte begin[];
//
begin = s.begin;
s.begin = nullptr;
size = s.size;
s.size = 0;
}
//
private:
int size ;
char* begin;
};
これにより、case 1およびcase 2の場合、コンパイラはデフォルトで移動コピーコンストラクタを呼び出し、このシーンで不要な深いコピーの問題を解決します.
この概念について説明します.
case 1とcase 2でこれらのコンパイラによって生成された一時オブジェクトは、カスタマイズされたオブジェクトとは異なり、変更できません.これにより、これらのオブジェクトを右値と呼び、変更できるものを左値と呼び、右値参照と左値参照の概念が多くなります.右値参照は上に移動して使用されます.右の値の参照はconst修飾を使用できません.変更するからです.
以上で終わるはずです.しかし、移動コピー(付与)コンストラクション関数を呼び出すシーンはたくさんあります.たとえば、次のようにします.
std::vector v1 = v2 ;
このようなコードは、どこでも見られますよ.もしv 2が非常に大きなオブジェクトであれば、私たちもv 2を使用する必要はありません.もちろん、深いコピーを望んでいません.それでは、モバイルコピー構造関数を呼び出すことができます.どのように呼び出すか、強制的に呼び出すか、moveが現れます.
std::vector v1 = std::move(v2) ;
moveの意味は,移動コピー(付与)構造関数を強制的に呼び出すことである.
OK、これでよくわかります.
最後に、moveの使用習慣をまとめます.
1.c++11以降、stlは移動構造関数をサポートし、moveをサポートします.
2.カスタムクラスは、自分で移動構造関数を実現するにはmoveが有効です.
3.moveを使用した後、元のオブジェクトを使用し続けることができなくなった理由は言うまでもないでしょう.