C++PrimerエッセイChapter 13コピー制御
7106 ワード
1.レプリケーション制御に含まれる内容:レプリケーションコンストラクタ、割り当てオペレータ、解析関数
2.コンストラクタのコピー:
a.定義:単一のパラメータのみであり、このパラメータはクラスタイプへの参照であり、このような構造関数は複製構造関数となる
b.適用状況:
(1)1つのタイプのオブジェクトに基づいてオブジェクトを表示または暗黙的に初期化する.
(2)オブジェクトをコピーし、パラメータとして関数に渡す
(3)関数から戻るときにオブジェクトをコピーする
(4)シーケンスコンテナ内の要素(?)を初期化する.
(5)要素初期化リストに基づいて配列要素(?)を初期化する.
3.C++の2つの初期化の形式:直接初期化とコピー初期化.
a.直接初期化は=記号を使用し、直接初期化は初期化式をカッコに入れます!ただし、クラスタイプオブジェクトで使用する場合、初期化のレプリケーション形式と直接形式は異なります.直接初期化呼び出しは実パラメータに一致するコンストラクション関数であり、レプリケーション初期化は常にレプリケーションコンストラクション関数を呼び出します.レプリケーション初期化では、まず指定したコンストラクション関数を使用して一時オブジェクトを作成し、その後、レプリケーションコンストラクション関数を使用してその一時オブジェクトを作成中のオブジェクトにコピーします.
b.通常、直接初期化とレプリケーション初期化は、低レベルの最適化にのみ差があります.しかし、レプリケーションのタイプがサポートされていない場合やexplicit構造関数を使用する場合、本質的な違いがあります.
4.代入オペレータ
a.合成割付オペレータ:メンバーごとの割付が実行されます.オペランドオブジェクトの各メンバーに対するオペランドオブジェクトへの割付が実行されます.グループを除いて、各メンバーが属するタイプの通常の方法で値を割り当てます.配列の場合、各配列要素に値を割り当てます.
b.賦値オペレータの戻りタイプは、内蔵タイプ賦値演算で返されるタイプと同じであるべきである.組み込み型の付与演算はオペランドのある参照を返します.したがって、コピーオペレータは同じクラスの適用も返します.
c.レプリケーションと割り当ては常に一緒に使用する
5.構造関数:
a.オブジェクトを取り消すと、自動的に析出関数が呼び出され、コンテナ内の要素は常に逆順序で取り消されます.
b.多くのクラスは、十分な関数を表示してはいけません.一部の作業が十分な関数を完了する必要がある場合にのみ、十分な関数を表示する必要があります.
c.3つの法則:関数を十分に分析する必要がある場合は、オペレータと構造関数をコピーする可能性があります.
d.合成解析関数:各非staticメンバーを逆順序で取り消します.
6.ポインタ・メンバーを管理する3つの方法:
a.ポインタメンバーは通常のポインタ型動作をとる.このようなクラスには、ポインタのすべての欠陥がありますが、特別なレプリケーション制御は必要ありません.
(1)デフォルトのコピー/付与とポインタ・メンバー(注:以下HasPtrはポインタ・メンバー変数の単純なクラス)
(2)ポインタ共有同一オブジェクト
(3)懸垂ポインタが発生する可能性がある
b.クラスはいわゆる「スマートポインタ」動作を実現することができる.ポインタが指すオブジェクトは共有されているが,クラスはポインタを垂れ下がることを防止できる.
2.コンストラクタのコピー:
a.定義:単一のパラメータのみであり、このパラメータはクラスタイプへの参照であり、このような構造関数は複製構造関数となる
b.適用状況:
(1)1つのタイプのオブジェクトに基づいてオブジェクトを表示または暗黙的に初期化する.
(2)オブジェクトをコピーし、パラメータとして関数に渡す
(3)関数から戻るときにオブジェクトをコピーする
(4)シーケンスコンテナ内の要素(?)を初期化する.
(5)要素初期化リストに基づいて配列要素(?)を初期化する.
3.C++の2つの初期化の形式:直接初期化とコピー初期化.
a.直接初期化は=記号を使用し、直接初期化は初期化式をカッコに入れます!ただし、クラスタイプオブジェクトで使用する場合、初期化のレプリケーション形式と直接形式は異なります.直接初期化呼び出しは実パラメータに一致するコンストラクション関数であり、レプリケーション初期化は常にレプリケーションコンストラクション関数を呼び出します.レプリケーション初期化では、まず指定したコンストラクション関数を使用して一時オブジェクトを作成し、その後、レプリケーションコンストラクション関数を使用してその一時オブジェクトを作成中のオブジェクトにコピーします.
1 string null_book = "9-99-999-99-9"; //copy initialization
2 string dots(10,'.'); //direct initialization
3 string empty_copy = new string(); //copy initialization
4 string empty_direct; //direct initialization
b.通常、直接初期化とレプリケーション初期化は、低レベルの最適化にのみ差があります.しかし、レプリケーションのタイプがサポートされていない場合やexplicit構造関数を使用する場合、本質的な違いがあります.
1 ifstream file1("filename");//ok :direct initialization
2 ifstream file2 = "filename";//error: copy constructor is private;
4.代入オペレータ
a.合成割付オペレータ:メンバーごとの割付が実行されます.オペランドオブジェクトの各メンバーに対するオペランドオブジェクトへの割付が実行されます.グループを除いて、各メンバーが属するタイプの通常の方法で値を割り当てます.配列の場合、各配列要素に値を割り当てます.
b.賦値オペレータの戻りタイプは、内蔵タイプ賦値演算で返されるタイプと同じであるべきである.組み込み型の付与演算はオペランドのある参照を返します.したがって、コピーオペレータは同じクラスの適用も返します.
1 class Sales_item{
2 public:
3 Sales_item & operator = ( const Sales_item &);
4 }
c.レプリケーションと割り当ては常に一緒に使用する
5.構造関数:
a.オブジェクトを取り消すと、自動的に析出関数が呼び出され、コンテナ内の要素は常に逆順序で取り消されます.
b.多くのクラスは、十分な関数を表示してはいけません.一部の作業が十分な関数を完了する必要がある場合にのみ、十分な関数を表示する必要があります.
c.3つの法則:関数を十分に分析する必要がある場合は、オペレータと構造関数をコピーする可能性があります.
d.合成解析関数:各非staticメンバーを逆順序で取り消します.
6.ポインタ・メンバーを管理する3つの方法:
a.ポインタメンバーは通常のポインタ型動作をとる.このようなクラスには、ポインタのすべての欠陥がありますが、特別なレプリケーション制御は必要ありません.
(1)デフォルトのコピー/付与とポインタ・メンバー(注:以下HasPtrはポインタ・メンバー変数の単純なクラス)
1 int obj = 0;
2 HasPtr ptr1(&obj, 42); //int * member points to obj ,val is 42
3 HasPtr PTRW(PTR1); //int * member ponts to obj,val is 42
(2)ポインタ共有同一オブジェクト
(3)懸垂ポインタが発生する可能性がある
b.クラスはいわゆる「スマートポインタ」動作を実現することができる.ポインタが指すオブジェクトは共有されているが,クラスはポインタを垂れ下がることを防止できる.
1 class U_ptr { 2 friend class HasPtr; 3 int *ip; 4 size_t use; 5 U_Ptr(int *p):ip(p),use(1){} 6 ~U_Ptr(){ delete ip;} 7 }; //
c. 。 , 。
1 class HasPtr { 2 public: 3 HasPtr(const int &p,int i):ptr(new int(p),val(i)) {} 4 HasPtr(const HasPtr &org):ptr(new int(*org.ptr)),val(orig.val){} 5 HasPtr& operator=(const HasPtr&); 6 ~HasPtr(){ delete ptr;} 7 private: 8 int *ptr; 9 int val; 10 };