1. 程式人生 > 實用技巧 >C++面向物件入門(九)深拷貝建構函式和淺拷貝建構函式

C++面向物件入門(九)深拷貝建構函式和淺拷貝建構函式

淺拷貝建構函式和深拷貝建構函式

淺拷貝建構函式

簡單的將類中的成員進行值複製, 當類的中的某個成員是指標型別時, 複製的是指標指向的地址, 即兩個物件指向的是堆上的同一塊記憶體

深拷貝建構函式

使用者(程式設計師)通過自己義拷貝建構函式使得在進行物件拷貝時, 對指標型別的成員, 在堆上重新開闢記憶體, 複製的是指標指向的記憶體地址儲存的資料, 而不是地址, 即拷貝後兩個物件的指標型別的成員指向的堆上兩塊地址不同的記憶體, 但是這兩塊記憶體所儲存的資料是一樣的
問: 為什麼需要重新定義淺拷貝建構函式?
答: 當類物件的成員包含指標型別變數時, 需要在使用時手動申請堆上的記憶體空間, 而堆上的記憶體空間的釋放由程式設計師來管理, 故常需要在解構函式中來釋放記憶體,


delete關鍵字是通過指標指向的地址來釋放記憶體的, 如果使用淺拷貝建構函式, 會導致同一塊記憶體被釋放多次, 就會產生異常. 故需要在拷貝時為新物件的該指標型別的成員變數重新申請記憶體, 而不是讓兩個物件的該指標型別的成員變數共用同一塊記憶體.

#include <iostream>
#include <string>

using namespace std;

/**
 * 淺拷貝建構函式和深拷貝建構函式
 * 淺拷貝建構函式:簡單的將類中的成員進行值複製, 當類的中的某個成員是指標型別時, 複製的是指標指向的地址, 即兩個物件指向的是堆上的同一塊記憶體
 * 深拷貝建構函式:使用者(程式設計師)通過自己定義拷貝建構函式使得在進行物件拷貝時, 對指標型別的成員, 在堆上重新開闢記憶體, 複製的是指標指向的記憶體地址儲存的資料, 而不是地址,
 * 即拷貝後兩個物件的指標型別的成員指向的堆上兩塊地址不同的記憶體, 但是這兩塊記憶體所儲存的資料是一樣的
 * 問: 為什麼需要重新定義淺拷貝建構函式?
 * 答: 當類物件的成員包含指標型別變數時, 需要在使用時手動申請堆上的記憶體空間, 而堆上的記憶體空間的釋放由程式設計師來管理, 故常需要在解構函式中來釋放記憶體,
 * delete關鍵字是通過指標指向的地址來釋放記憶體的, 如果使用淺拷貝建構函式, 會導致同一塊記憶體被釋放多次, 就會產生異常. 故需要在拷貝時,
 * 為新物件的該指標型別的成員變數重新申請記憶體, 而不是讓兩個物件的該指標型別的成員變數共用同一塊記憶體.
 
*/ class Rider { public: Rider() { } Rider(string name) { this->name = name; cout << "Rider類建構函式呼叫" << endl; } Rider(string name, string status) { this->name = name; this->status = new string; *this->status = status; cout
<< "Rider類建構函式呼叫" << endl; } /** * 自定義深拷貝函式 * @param r 欲拷貝的物件 */ Rider(const Rider &r) { this->name = r.name; this->status = new string ; *this->status = *r.status; } ~Rider() { cout << "The Rider's name is " << name << endl; cout << "The Rider's status is " << *status << endl; cout << "Rider類解構函式呼叫" << endl; if (status != NULL) { delete status; status = NULL; } } private: string *status; string name; }; void test1() { Rider zeroOneRH("Zero One"); Rider zeroOneBS(zeroOneRH); } void test2() { Rider zeroOneRH("Zero One", "Rising Hopper"); Rider zeroOneBS(zeroOneRH); int a = 10; } int main() { // test1(); test2(); system("pause"); return 0; }