C++中的拷貝構造詳解
拷貝構造函數
同一個類的對象在內存中有完全相同的結構,如果作為一個整體進行復制或稱拷貝是完美可行的,這個拷貝過程隻需要拷貝數據成員,而函數成員是公用的(隻有一份代碼);在建立對象時可用同一類的另一個對象來初始化該對象的存儲空間,這時所用的構造函數稱為拷貝構造函數
例如:
class Object { int value; public: Object(int x = 0) :value(x) {} ~Object() {} Object(Object& obj):value(obj.value) { cout << "Copy Create" << endl; } }; int main() { Object obja(10); Object objb(obja);//一個對象初始化另一個對象空間,調用拷貝構造 }
當一個對象去初始化另一個對象空間,調用拷貝構造;若類中沒有寫拷貝構造,如同構造函數與析構函數一樣,系統會生成一個缺省的拷貝構造函數
OBject(Object& obj) {}
拷貝構造中的引用
如果我們在寫的拷貝構造不加引用,這樣會引起死遞歸
//Object(Object& obj):value(obj.value) Object(Object obj):value(obj.value) { cout << "Copy Create" << endl; }
為什麼拷貝構造函數必須采用引用傳參,否則會引發無窮遞歸呢?
這個問題其實很簡單,再復制對象時要分為兩個步驟:
第一步:開辟一個臨時空間;
第二步:由於臨時空間是需要構造的,重新調用拷貝構造函數(無窮遞歸形成…)
同時我們可以在拷貝構造參數前加上一個引用,來限制可能會出現的問題
//Object(Object& obj):value(obj.value) Object(const Object& obj):value(obj.value) { cout << "Copy Create" << endl; } //這裡的const修飾,令我們不能修改被拷貝對象
什麼情況會使用拷貝構造
拷貝構造不止在使用一個對象去構造另一個對象時調用,在下面這些情況也會調用:
class Object{int value;public:Object(){cout << "Object::Object" << this << endl;}Object(int x = 0) :value(x){cout << "Object::Object" << this << endl;}~Object(){cout << "Objecet::~Object" << this << endl;}Object(Object& obj) :value(obj.value){cout << "Copy Create" << this << endl;}void SetValue(int x) { value = x; }int GetValue() const { return value; }};Object fun(Object obj){int val = obj.GetValue();Object obja(val);return obja;}int main(){Object objx(0);Object objy(0);objy = fun(objx);return 0;}class Object { int value; public: Object() { cout << "Object::Object" << this << endl; } Object(int x = 0) :value(x) { cout << "Object::Object" << this << endl; } ~Object() { cout << "Objecet::~Object" << this << endl; } Object(Object& obj) :value(obj.value) { cout << "Copy Create" << this << endl; } void SetValue(int x) { value = x; } int GetValue() const { return value; } }; Object fun(Object obj) { int val = obj.GetValue(); Object obja(val); return obja; } int main() { Object objx(0); Object objy(0); objy = fun(objx); return 0; }
在上面這一段代碼中,我們總共創建瞭幾個對象呢,我們來看一下
首先①②屬於對象的構造,調用構造函數;程序運行到objy = fun(objx);進入到fun函數,這是構造臨時對象obj③屬於拷貝構造;隨後④構造對象obja;最後⑤這裡也屬於拷貝構造也需要創建一個臨時對象(將亡值)
並且我們無法將fun函數中obja對象之間return傳回給objy,因為在函數結束時obja會析構失效,所以這裡會創建一個新的臨時對象
總結
本篇文章就到這裡瞭,希望能夠給你帶來幫助,也希望您能夠多多關註WalkonNet的更多內容!