コンストラクション/プロファイル/割り当て演算
4635 ワード
条項05:C++が黙々と作成して呼び出す関数を理解する
空のクラスを書いたら
コンパイラはこのクラスにdefaultの関数を追加します.
ここで、コンパイラが作成したcopyコンストラクタとcopy assigmentオペレータは、ソースオブジェクトのnon-staticメンバー変数を単純にターゲット変数にコピーするだけです.コンパイラが作成するcopy assigmentオペレータは、copyコンストラクション関数とほぼ同じ動作をしますが、一般的には、生成されたコードが合法的で、意味があることを証明する適切な機会がある場合にのみ、コンパイラはcopy assigmentオペレータを作成します.たとえばクラスにconstまたは参照フィールドがある場合、コンパイラはcopy assigmentオペレータの作成を拒否することが多い.
クラスにコンストラクション関数を宣言した場合、コンパイラはクラスにdefaultコンストラクション関数を追加しません.
条項6:コンパイラが自動的に生成する関数を使用しない場合は、明確に拒否する必要があります.
defaultコンストラクション関数とコンストラクション関数を使用したくない場合は、コンストラクション関数とコンストラクション関数を宣言することで拒否できます.
ただし、copyコンストラクション関数とcopy assigmentオペレータを使用したくない場合は、たとえば、次の操作は許可されません.
どのようにして上記の2つの状況を拒否することができますか?
1つの方法は、copyコンストラクション関数とcopy assigmentオペレータをprivateとして宣言することです.これにより、外部でこの2つのメソッドを呼び出すことができず、コンパイラも自分で追加しません.しかし、ユーザmember関数またはfriend関数は両方のメソッドに呼び出される可能性があるため、この2つのメソッドのみを宣言して実装せず、不注意で呼び出されると接続エラー(Link Error)が得られます.
もう1つの方法は、可能な接続エラーをコンパイル期間に繰り上げることもできます.方法は、前の方法で宣言されたUncopyをブロックしたい他のクラスは、ベースクラスを継承するだけでよいUncopyableのベースクラスを定義します.
条項7:マルチステートベースクラスにvirtual構造関数を宣言する
条項8:異常を構造関数から逃がすな
条項9:コンストラクション関数でvirtual関数を呼び出さないでください.
条項10:operator=reference to*thisを返す
a=b=cなどの連鎖複製を実現することができる.
この条項はoperator+=,-=,*=,/=などにも適用されます.
条項11:operator=での自己付与の処理
例:
自己付与を処理するもう1つの方法:
条項12:対象を複製する時、その各成分を忘れないでください
確認する必要があります:1.すべてのlocalメンバー変数をコピーします.2.すべてのbase classes内の適切なcopying関数を呼び出します.
空のクラスを書いたら
class Empty { };
コンパイラはこのクラスにdefaultの関数を追加します.
class Empty {
public:
Empty() { ... } //default
Empty(const Empty& rhs) { ... } //copy
~Empty() { ... } //
Empty & operator=(const Empty& rhs) { ... } //copy assigment
};
ここで、コンパイラが作成したcopyコンストラクタとcopy assigmentオペレータは、ソースオブジェクトのnon-staticメンバー変数を単純にターゲット変数にコピーするだけです.コンパイラが作成するcopy assigmentオペレータは、copyコンストラクション関数とほぼ同じ動作をしますが、一般的には、生成されたコードが合法的で、意味があることを証明する適切な機会がある場合にのみ、コンパイラはcopy assigmentオペレータを作成します.たとえばクラスにconstまたは参照フィールドがある場合、コンパイラはcopy assigmentオペレータの作成を拒否することが多い.
クラスにコンストラクション関数を宣言した場合、コンパイラはクラスにdefaultコンストラクション関数を追加しません.
条項6:コンパイラが自動的に生成する関数を使用しない場合は、明確に拒否する必要があります.
defaultコンストラクション関数とコンストラクション関数を使用したくない場合は、コンストラクション関数とコンストラクション関数を宣言することで拒否できます.
ただし、copyコンストラクション関数とcopy assigmentオペレータを使用したくない場合は、たとえば、次の操作は許可されません.
Object a1;
Object a2;
Object a3(a1); //
Object a2 = a1; //
どのようにして上記の2つの状況を拒否することができますか?
1つの方法は、copyコンストラクション関数とcopy assigmentオペレータをprivateとして宣言することです.これにより、外部でこの2つのメソッドを呼び出すことができず、コンパイラも自分で追加しません.しかし、ユーザmember関数またはfriend関数は両方のメソッドに呼び出される可能性があるため、この2つのメソッドのみを宣言して実装せず、不注意で呼び出されると接続エラー(Link Error)が得られます.
もう1つの方法は、可能な接続エラーをコンパイル期間に繰り上げることもできます.方法は、前の方法で宣言されたUncopyをブロックしたい他のクラスは、ベースクラスを継承するだけでよいUncopyableのベースクラスを定義します.
class Uncopyable {
protect:
Uncopyable () {}
~Uncopyable () {}
private:
Uncopyable(const Uncopyable&);
Uncopyable& operator=(const Uncopyable&);
};
// Uncopyable
class NewClass : private Uncopyable {
...
};
条項7:マルチステートベースクラスにvirtual構造関数を宣言する
条項8:異常を構造関数から逃がすな
条項9:コンストラクション関数でvirtual関数を呼び出さないでください.
条項10:operator=reference to*thisを返す
a=b=cなどの連鎖複製を実現することができる.
この条項はoperator+=,-=,*=,/=などにも適用されます.
条項11:operator=での自己付与の処理
例:
Widget& Widget::operator=(const Widghet& rhs) {
if (this == &rhs)
return *this;
...
return *this;
}
自己付与を処理するもう1つの方法:
//copy and swap
Widget& Widget::operator=(const Widghet& rhs) {
Widget tem(rhs);
swap(temp);
return *this;
}
条項12:対象を複製する時、その各成分を忘れないでください
確認する必要があります:1.すべてのlocalメンバー変数をコピーします.2.すべてのbase classes内の適切なcopying関数を呼び出します.