C++ベースのコピーコンストラクタ

1927 ワード

各C++クラスには1つの構造関数しかありませんが、複数の構造関数と複数の付与関数があります.コンストラクション関数には、デフォルトコンストラクション関数(パラメータなし、またはパラメータがすべてデフォルト)が含まれ、コンストラクション関数をコピーします.プログラミングでは、プログラマが上記の関数を明示的に宣言して定義しない場合、コンパイラは4つのpublic inlineのデフォルト関数を自動的に生成します.形式は次のとおりです.
A();
A(const A&);
A& operator=(const A& a)
~A();
【コピーコンストラクタを明示的に定義する必要がある場合】
デフォルトのコピーコンストラクション関数と付与関数は、いずれも浅いコピー(ビットコピー)を使用します.コピーコンストラクション関数は、値によって渡される方法で関数にオブジェクトを渡し、返します.クラスのメンバーにポインタがある場合、このコピー方式の結果、2つの異なるオブジェクトのポインタが同じメモリ領域を指し、アクセス競合、複数回deleteなどのエラーが発生しやすく、私たちが望んでいるものではありません.
class Widget
{
public:
	int* pi;
};

 
	int i1 = 5;
	int i2 = 9;
	
	Widget w1;
	w1.pi = &i1;
	
	Widget w2(w1);
	std::cout << *(w2.pi) << std::endl; //output 5
	
	*(w2.pi) = i2;
	std::cout << *(w1.pi) << std::endl; //output 9
	std::cout << *(w2.pi) << std::endl; //output 9

注意Widget w 2=w 1;コピーコンストラクタが呼び出され、値を割り当てるのではなく、混同を避けるためにWidget w 2(w 1)と書くことが望ましい.コピーコンストラクション関数を呼び出すと、新しいオブジェクトが生成されるに違いない.
オブジェクトw 2のpiポインタの値を変更すると、w 1の値も変更されます.2つのオブジェクトのpiポインタが同じメモリ領域を指しているためです.このエラーは、クラスでバッファが定義されている場合に発生しやすい.
構造関数、コピー構造関数、および付与演算子の3つは、ほとんど同時に表示されます.構造関数は一般的にリソースを解放するために使用され、クラスでポインタタイプが定義される可能性が高いため、コピー構造関数と付与演算子を明示的に定義する必要があります.
【コピー禁止】
C++ではクラスで物事を表すが、多くのクラスが表す概念は「コピー」という動作について明確な定義がない.例えば、「接続」、「ウィンドウ」、「ファイル」などである.1つの接続をコピーします.2つの接続の関係は何ですか.2つのパラメータの同じ接続が得られたのか、それとも2つのオブジェクトが同じ接続を指しているのか.この場合、二義性を回避するには、コピー構造関数とリロード付与演算子をprivateに設定することでコピーを禁止することができる.
class Widget
{
public:
	int* pi;
private:
	Widget(const Widget&);
	Widget& operator=(const Widget&);
};

VS 2010では、このように宣言すると、上記のテストコードに対して、「no appropriate default constructor available.」
 
【参考】
Solmyrのエッセイシリーズの8:コピー