コピーコンストラクタと代入演算子が呼び出されるタイミング

オブジェクトのコピー

インスタンスをコピーする際にはコピーコンストラクタと呼ばれるコンストラクタが暗黙のうちに呼び出されています。コピーコンストラクタと代入演算子を明示して実際に呼び出されているタイミングを確認してみます。次のArrayクラスのインスタンスをコピーする場合として5つの場合を考えてみます。

class Array
{
public:
	Array();
	Array(const Array& ary);	//copy constructor
	Array& operator=(const Array& ary);
private:
	int m_var;
};

#include <iostream>
using namespace std;
Array::Array(){
}
Array::Array(const Array& ary){
	cout<<"copy constructor"<<endl;
}
Array& Array::operator=(const Array& ary){
	cout<<"operator="<<endl;
	return *this;
}

Case1 代入による初期化

Array u;
Array v=u;	//case 1

Case2 初期化

Array u;
Array v(u);	//case 2

Case3 引数

void func1(Array a){
}
int main()
{
	Array a;
	func1(a);	//case 3

	return 0;
}

Case4 返却値

Array func2(){
	return Array a;
}
int main()
{
	func2();	//case 4
	return 0;
}

Case5 代入

Array a;
Array b;
b=a;		//case 5

コピーコンストラクタの呼び出し

Case1〜4のように、同じクラスのインスタンスによってコピーと初期化を行う場合にコピーコンストラクタが呼び出されているのが分かります。

void func1(Array a){
}
Array func2(){
	Array b;
	return b;
}
int main()
{
	Array u;

	Array v=u;	//case 1
	Array w(u);	//case 2
	func1(v);	//case 3
	func2();	//case 4

	return 0;
}


copy constructor
copy constructor
copy constructor
copy constructor

代入演算子の呼び出し

一方代入演算子は、Case5のようにオブジェクトを代入する際に呼び出されています。

int main()
{
	Array a;
	Array b;
	b=a;		//case 5
	return 0;
}


operator=
Case1と5は混同しやすいですが、Case1のようにコピー先のインスタンスの値がまだ確定していなくて、初期化をしなければならないときにはコピーコンストラクタが呼ばれます。Case5のように、既にインスタンスの値が確定していて、インスタンス間で値をコピーする場合に代入演算子が呼び出されるわけです。