聊聊C++中複製構造函數和賦值操作符

複製構造函數:只有單個形參,而且形參是對本類類型對象的引用(常用const修飾),這樣的構造函數稱爲複製構造函數。與默認構造函數一樣,複製構造函數可由編譯器隱式調用。複製構造函數可以用於:

  • 根據另一個同類型的對象顯式或隱式初始化一個對象
  • 複製一個對象,將它作爲實參傳給一個函數
  • 從函數返回時複製一個對象
  • 初始化順序容器中的元素
  • 根據元素初始化列表初始化數組元素
賦值操作符:與複製構造函數一樣,如果沒有定義自己的賦值操作符,則編譯器會合成一個。

下面我寫了一個程序對以上描述做出解釋。

#include<iostream>
#include<string>
#include<vector>
using namespace std;
class Test
{
public:
	Test(){str="Kevin";x=10;cout<<"default constructor"<<endl;}				//construction function
	Test(const Test& t){str=t.str;x=t.x; cout<<"copy construction was used!"<<endl;}	//copy constructor 
	Test& operator=(const Test& t){str=t.str;x=t.x;cout<<"operator="<<endl;return *this;}	
private:												
	string str;
	int x;
};
Test f(Test t)
{
	cout<<"f function"<<endl;
	return t;
}
main()
{
	cout<<"Test t:"<<endl;
	Test t;

	cout<<endl<<"vector<Test> vec1(5):"<<endl;
	vector<Test> vec1(5);

	cout<<endl<<"vector<Test> vec2(5,t):"<<endl;
	vector<Test> vec2(5,t);

	cout<<endl<<"Test te[5]:"<<endl;
	Test te[5];

	cout<<endl<<"Test t2(t):"<<endl;
	Test t2(t);

	cout<<endl<<"f(t2):"<<endl;
	f(t2);

	cout<<endl<<""<<endl;
	Test* p1=new Test();
	*p1=t;
	Test* p2=&t;
	Test t3=t;
	Test t4;
	t4=t;
}


以上程序的輸出結果是:

default constructor

vector<Test> vec1(5):
default constructor
copy construction was used!
copy construction was used!
copy construction was used!
copy construction was used!
copy construction was used!

vector<Test> vec2(5,t):
copy construction was used!
copy construction was used!
copy construction was used!
copy construction was used!
copy construction was used!

Test te[5]:
default constructor
default constructor
default constructor
default constructor
default constructor

Test t2(t):
copy construction was used!

f(t2):
copy construction was used!
f function
copy construction was used!


default constructor
operator=
copy construction was used!
default constructor
operator=


     由上面程序中的第26行可以看出,複製構造函數被用於初始化容器元素的時候,如果沒有之處元素的初始值,則編譯器會首先調用默認的構造函數創建一個臨時制,然後使用複製構造函數將臨時制複製到每一個元素中。當指明瞭元素的初始值(如29行所示)時,編譯器會直接將其複製到每一個元素。

     由程序中第32行的運行結果可以看出,定義一個類類型的數組時,編譯器會利用類的默認構造函數初始化每一個元素。

由程序中第38行的運行結果可以看出,當類類型被用做形參與返回值時,各自發生了一次複製。C++ primer中這樣描述:“當函數的形參爲非引用類型的時候,將複製實參的值。類似的,以非引用類型做返回值時,將返回return語句中的值的副本”。按照我的理解就是“當形參和返回值都不是引用時,進入函數時發生一次複製,離開函數時發生一次複製”。

     程序的第41行至第46行是爲了說明覆制構造函數與賦值操作符的區別設計的。我們可以看到*p1=t;這一句用到了賦值操作符,t4=t;這一句也用到了賦值操作符,其他各種形式的語句都用的是複製構造函數。從中可以總結出一句話“從無到有是copy,從有到有是賦值”。這句話怎麼理解呢?大家看,*p1=t這一句中的*p是早已經聲明瞭的,在*p1聲明的時候已經完成了它的初始化。在*p1=t這句中*p是已經初始化過的,所以這裏*p1=t應用的是賦值操作符。同理第46行的中的t4也是一個已經聲明過,完成了初始化的變量,所以在語句t4=t中使用的也是賦值操作符。而在Test t3=t;  這樣的語句中,t3是剛剛聲明出來的,還沒有初始化,要求編譯器按照t的內容初始化t3。這正好是複製構造函數的作用。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章