C ++ 11件の移動セマンティクス

[1]なぜ移動セマンティクスの導入?

その後、C ++プログラミングにおける実践のメンバーがほとんど最も合理的であるとみなすことが、ポインタの内容をコピーして新しいメモリコピーコンストラクタを割り当てます。

しかし、いくつかのケースでは、我々は、これはコンストラクタのセマンティクスをコピーする必要がないことがわかります。次の例:

1の#include <iostreamの>
 2  使用して 名前空間STDを、
3  
4  クラスHasPtrMem
 5  { 
 6  公共7      HasPtrMem():D(新しい INT0 ))
 8      { 
 9          COUT << " 構築物:" << ++ n_cstr << ENDL。
10      } 
 11      HasPtrMem(CONST HasPtrMem&H):D(新しい INT(* HD))
 12      { 
 13          COUT <<" コピーコンストラクト:" << ++ n_cptr << ENDL;
 14      }
 15HasPtrMem()
 16      { 
 17。          COUT << " 自爆:" << ++ n_dstr << ENDL;
 18である     } 
 。19      
20は、     INT * D;
 21は、     静的 int型の n_cstr; // コンストラクタ呼び出しの数を数える
22は     、静的な int型の n_dstr; // デストラクタ呼び出しの数を数える
23は     、静的な int型の n_cptr; // 呼び出しコピーコンストラクタの数カウント
24を };
25  
26  INT HasPtrMem :: n_cstr = 0 27  INT HasPtrMem :: n_dstr = 0 ;
28  INT HasPtrMem :: n_cptr = 0 ;
29  
30  HasPtrMem GetTemp()
 31  { 
 32      リターンHasPtrMem()。
33  } 
 34  
35  のint main()の
 36  { 
 37      HasPtrMem A = GetTemp()。
38 }

これは、関数がHasPtrMemオブジェクトを返す宣言します。

レコードコンストラクタ、コピーコンストラクタ、デストラクタ、および3つの静的変数を使用したコール数、へ。

主な機能には、HasPtrMemは、単にそれがGetTempの戻り値の使用が初期化される必要があり、オブジェクトaを宣言します。

このプログラムをコンパイルして実行するには、次のような出力が表示されます。

構築物:1 
コピー構造:1 
デストラクト:1 
コピー構文:2 
デストラクト:2 
デストラクト:3

これはGetTemp機能HasPtrMem()式を明示的コンストラクタを呼び出し、プリントアウトされ、いったんコンストラクタが呼び出されます。

コピーコンストラクタは二回呼ばれていました:

GetTemp HasPtrMemのから生成された()関数後変数が戻り値GetTempとして使用されるように、一時的な値の量を構成するコピー。

また、一時的な値は、コールの主なオブジェクトから構成されています。

これに対応し、デストラクタは、3回を呼び出します。全体のプロセスを以下に示します。

ほとんどの不安は、コールコピーコンストラクタです。上記の例では、唯一のクラスHasPtrMemのint型のポインタを有しています。

非常に大きなヒープデータへのポインタHasPtrMem場合、プロセスは、設定は非常に高価でコピーします。

この問題が発生すると考えられる、初期化式の実行速度はかなり心配になります。

それは何をすべきか腫れ?私たちは再び、上の図の主な機能の一部であり、一時的なオブジェクトに焦点を当てを見てみましょう。

意味論によると、文の終了後にC ++デストラクタでの一時的なオブジェクトは、それが含まれているヒープメモリのリソースを解放します。

コピーコンストラクタ時間を作るが、それは、ヒープメモリが割り当てられます別の割り当てはあまり意味がしていないようなリリースを。

だから我々は、それはそれのいわゆるコピーコンストラクタのセマンティクスを使用せずに、ある、一時的なオブジェクトの構築時にメモリを割り当てることができない場合は?

[2]移動セマンティクス

問題の部分については、実際には、問題の本当のコア:

一時オブジェクトのデストラクタが再び座ることになる前に、我々はそのプロセスの同じ過剰を適用し、メモリの内容をコピーします。

そんなに無駄な努力を行うには、新しい方法は、(モバイルコピーコンストラクタコンストラクタ関数で)下記を参照してください。

上部(コピーモードの設定):

新しいヒープメモリに割り当てられたコピーを実行すると、広告の一時的なオブジェクトにヒープからメモリの内容をコピーするときにオブジェクトのコピーが一時オブジェクトから構成されている場合。

設定が完了したら、それはヒープメモリリソースがデストラクタをリリースされる予定があるので、一時的なオブジェクトは、破壊されます。

下半分(モバイルモードの設定):

一時的なヒープメモリのリソース広告尖ったオブジェクトを構築するには。

同時に、我々は一時的なオブジェクトが(次のコードを達成する方法を示しています)、それはヒープメモリを指して解放しないことを確認してください。

その後、工事が完了した後、一時的なオブジェクトは、Aからのリソースを所有していた一時オブジェクトへのヒープメモリを「盗む」に、破壊されていても。

そのような一時的なオブジェクトのコンストラクタリソースが呼び出され、「盗まれた」「モバイルコンストラクタ」としてC ++、11 そして、これは動作を「盗む」、「移動セマンティクス」(移動セマンティクス)と呼ばれています。

次のコードの実装を考えてみましょう:

 1 #include <iostream>
 2 using namespace std;
 3 
 4 class HasPtrMem
 5 { 
 6 public:
 7     HasPtrMem() : d(new int(0))
 8     { 
 9         cout << "Construct: " << ++n_cstr << endl;
10     } 
11     HasPtrMem(const HasPtrMem & h) : d(new int(* h.d))
12     { 
13         cout << "Copy construct: " << ++n_cptr << endl;
14     }
15     HasPtrMem(HasPtrMem&& h) : d(h.d)   // 移动构造函数
16     {
17         h. d = nullptr;  // 将临时值的指针成员置空
18         cout << "Move construct: " << ++n_mvtr << endl;
19     }
20     ~ HasPtrMem()
21     { 
22         cout << "Destruct: " << ++n_dstr << endl;
23     } 
24     
25     int* d;
26     static int n_cstr; // 统计构造函数调用次数 
27     static int n_dstr; // 统计析构函数调用次数
28     static int n_cptr; // 统计拷贝构造函数调用次数
29     static int n_mvtr; // 统计移动构造函数调用次数
30 };
31 
32 int HasPtrMem::n_cstr = 0;
33 int HasPtrMem::n_dstr = 0;
34 int HasPtrMem::n_cptr = 0;
35 int HasPtrMem::n_mvtr = 0;
36 
37 HasPtrMem GetTemp()
38 {
39     HasPtrMem h;
40     cout << "Resource from " << __func__ << ": " << hex << h.d << endl;
41     return h;
42 } 
43 
44 int main()
45 { 
46     HasPtrMem a = GetTemp();
47     cout << "Resource from " << __func__ << ": " << hex << a.d << endl;
48 }
49 
50 /*
51 Construct: 1                     // 调用构造函数,构造对象h
52 Resource from GetTemp: 0x603010  // GetTemp函数中打印对象h的资源
53 Move construct: 1                // 由对象h,调用移动构造函数,构造临时对象
54 Destruct: 1                      // 析构掉对象h
55 Move construct: 2                // 由临时对象,调用移动构造函数,构造对象a
56 Destruct: 2                      // 析构掉临时对象
57 Resource from main: 0x603010     // main函数中打印对象a的资源[本质上来自于对象h的资源]
58 Destruct: 3                      // 析构掉对象a
59 */

如上。

good good study, day day up.

顺序 选择 循环 总结

 

おすすめ

転載: www.cnblogs.com/Braveliu/p/12233670.html