拷貝建構函式應用的場合由以下幾個方面:
1 函式的引數是乙個物件,並且是值傳遞方式
2 函式的返回值是乙個物件,並且是值傳遞方式
3 用乙個物件初始化另外乙個物件
由此,當函式的引數或者返回值為乙個物件時,使用的時候要小心,因為值傳遞的時候執行的是位拷貝,並不會呼叫物件的建構函式,也就是說生成的臨時物件可能不是正確初始化的,這樣就可能會出現一些意向不到的問題。當返回值是個物件和用乙個物件初始化另外乙個物件時的情況是相同的。
比如如下**:
#include
using namespace std;
class ctest
public:
int i;
ctest()
~ctest()
void test(ctest obj)
int main()
ctest testobj;
test(testobj);
return 0;
這個程式執行的結果為:
construct
discontruct
discontruct
呼叫了一次建構函式,呼叫了兩次析構函式。宣告testobj物件時,呼叫了一次建構函式。當testobj以值傳遞的方式傳入test函式時,此時會生成乙個ctest型別的臨時變數,但是此時編譯器採用的是位拷貝的方式,並不呼叫ctest類的建構函式。當test函式退出時,生成的臨時變數生命週期結束,呼叫一次析構函式,當main函式退出時,testobj變數生命週期結束,呼叫一次析構函式。所以出現上面的輸出。
正確的解決方法是定義乙個拷貝建構函式。
拷貝建構函式的型別為:yourclass&(yourclass& object);
修改後的**為:
#include
using namespace std;
class ctest
public:
int i;
ctest()
ctest(ctest& obj) //拷貝建構函式
~ctest()
void test(ctest obj)
int main()
ctest testobj;
test(testobj);
return 0;
此時程式的輸出為:
construct
call copy construct
discontruct
discontruct
當用乙個物件初始化另外乙個物件時,也對呼叫拷貝建構函式。
如ctest test1;
ctest test2 = test1; //呼叫test1的拷貝建構函式初始化物件test2
但是對於下面的表示式:
ctest test1,test2;
test2 = test1;
卻不會呼叫ctest的拷貝建構函式,因為test2已經被初始化過了,此時如果想要正確對test2賦值,需要過載運算子=
運算子過載的方式為 :
yourclass& operator=(yourclass& obj)
return *this;
雖然不編寫拷貝建構函式和過載運算子=,在大部分的情況下**都能正常工作,因為編譯器會生成乙個預設的拷貝建構函式並且在物件賦值的時候也會作些特殊處理。但是我們不能完全相信系統始終能正常理解你的**。所以讓**完全在自己的控制之下才是乙個好的方法。所以時刻不要忘記編寫拷貝建構函式和過載=
拷貝建構函式與賦值運算子過載
拷貝建構函式 只有單個形參,該形參是對本類型別物件的引用 一般常用const修飾 在用已存在的類型別物件建立新物件時由編譯器自動呼叫。1.拷貝建構函式是建構函式的乙個過載形式 class date date const date d private int year int month int da...
拷貝建構函式與過載賦值運算子
注意 該作者部落格已遷移至 如果乙個建構函式的第乙個引數是自身類型別的引用,且任何額外的引數都有預設值,則此建構函式是拷貝建構函式。c premier裡的定義 拷貝建構函式應用的場景 預設拷貝建構函式 class ctest ctest void test ctest obj intmain 這個程...
C 之拷貝建構函式和複製運算子過載
1 c 拷貝建構函式 拷貝建構函式是為了解決如神明物件時候就用乙個已經存在的物件來初始化這個新的物件,如mystring a b 這裡b是已經存在mystring物件。但是這裡需要注意拷貝建構函式裡面的內部實現細節。這裡面其實是在這個a物件類的定義中定義了拷貝建構函式的格式如 mystring co...