拷貝構造函數:
複制構造函數是一種特殊的構造函數,具有單個形參,該形參(常用const修飾)是對該類類型的引用。
當定義一個新對象并用一個同類型的對象對它進行初始化時,将顯示使用複制構造函數。
當該類型的對象傳遞給函數或從函數傳回該類型的對象時,将隐式調用複制構造函數。成員的拷貝,有指針的話,就會有指針拷貝,兩個指針指在同一片位址,引用同理。T::T(const T&);兩種拷貝構造的方式
#include <iostream>
using namespace std;
class A
{
private:
int i;
public:
A(void) : i(10)
{
cout << "A::A():" << i << endl;
}
// 複制構造函數(也稱為拷貝構造函數)
// 複制構造函數參數為類對象本身的引用,用于根據一個已存在的對象複制出一個新的該類的對象,一般在函數中會将已存在對象的資料成員的值複制一份到新建立的對象中
// 若沒有顯示的寫複制構造函數,則系統會預設建立一個複制構造函數,但當類中有指針成員時,由系統預設建立該複制構造函數會存在風險,具體原因請查詢有關 “淺拷貝” 、“深拷貝”的文章論述
A(const A &c) : i()
{
cout << "A::A(const A & c):" << i << endl;
}
};
int main()
{
cout << "a:" << endl;
A a;
cout << "b:" << endl;
A b = a;
cout << "c:" << endl;
A c(a);
}
//結果:
a:
A::A():10
b:
A::A(const A & c):0
c:
A::A(const A & c):0
什麼情況使用複制構造函數:
類的對象需要拷貝時,拷貝構造函數将會被調用。
以下情況都會調用拷貝構造函數:
- 一個對象以值傳遞的方式傳入函數體;
- 一個對象以值傳遞的方式從函數傳回&;
- 一個對象需要通過另外一個對象進行初始化。
深拷貝和淺拷貝:
所謂淺拷貝,指的是在對象複制時,隻對對象中的資料成員進行簡單的指派,預設拷貝構造函數執行的也是淺拷貝。
在“深拷貝”的情況下,對于對象中動态成員,就不能僅僅簡單地指派了,而應該重新動态配置設定空間(在拷貝構造函數裡重新配置設定空間)
上面提到,如果沒有自定義複制構造函數,則系統會建立預設的複制構造函數,但系統建立的預設複制構造函數隻會執行“淺拷貝”,即将被拷貝對象的資料成員的值一一指派給新建立的對象,若該類的資料成員中有指針成員,則會使得新的對象的指針所指向的位址與被拷貝對象的指針所指向的位址相同,delete該指針時則會導緻兩次重複delete而出錯。
如果一個類裡面有一個指針,如果沒有重載拷貝構造,c++會自動拷貝一個指在同一個位址的指針。
![](https://img.laitimes.com/img/_0nNw4CM6IyYiwiM6ICdiwiIyVGduV2YfNWawNCM38FdsYkRGZkRG9lcvx2bjxiNx8VZ6l2cs0TP310dJRkTy0kaNBDOsJGcohVYsR2MMBjVtJWd0ckW65UbM5WOHJWa5kHT20ESjBjUIF2X0hXZ0xCMx81dvRWYoNHLrdEZwZ1Rh5WNXp1bwNjW1ZUba9VZwlHdssmch1mclRXY39CXldWYtlWPzNXZj9mcw1ycz9WL49zZuBnLzcTN0ITN1kTMzEDMxAjMwIzLc52YucWbp5GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.png)
第一個是拷貝構造,第二個是直接用who去初始化外面的p
Person copy_func(char *who)
{
Person local(who);
local.print();
return locall
}
Person nocopy_func(char *who)
{
return Person(who);
}
前面有類型的都是初始化,無類型的就是指派
碰見string變量,拷貝指針的時候,會調用string類的拷貝構造函數。
寫個類就要寫構造函數、析構函數、拷貝構造函數。