淺拷貝與深拷貝

官網快三註冊邀請碼88886486發表於2018-12-19

淺拷貝與深拷貝

在上一節講解的拷貝建構函式的例子Circle類中,拷貝的策略都是與系統預設的策略一致,即把原有物件中成員依次拷貝給新物件中對應的成員,既然如此,我們為何還要自己定義呢?原因在於,簡單的將所有情況都按照這種簡單的方式初始化,難免有不同的情況,出現問題。

例如,剛才的Circle類中,如果成員變數中加一個指標成員,初始化中需要動態開闢記憶體,則會出現極大的安全隱患,程式碼如下:

/********************************** //Des:C++教程配套程式 //Author:Huang //CopyRight:www.dotcpp.com //Date:2017/8/26 **********************************/

include

include

using namespace std;

define PI 3.1415

class Circle { private: double R; char *str; public: Circle(double R,char *str); ~Circle(); double area(); double girth(); }; Circle::~Circle() { delete []str; } Circle::Circle(double R,char *str) { cout<<"Constructor"<<endl; this->R = R; this->str = new char[strlen(str)+1]; strcpy(this->str,str); cout<R<<" "<str<

double Circle::area() { return PI*R*R; } double Circle::girth() {

return 2*PI*R;

} int main() {

Circle A(5,"NO.1 Old class");
Circle B(A);
return 0;

} 為了驗證,在Circle類中,我們增加了一個指標成員,並且在建構函式中對其初始化,同時沒有自定義拷貝建構函式。那麼在主函式中Circle B(A);的這句話將A物件賦值給B物件,將呼叫預設生成的拷貝建構函式,執行後,程式如下圖報錯

qian.png

而實際上的原因在於,預設的拷貝建構函式僅僅是進行資料賦值,並不能為指標開闢記憶體空間,相當於程式碼:

This->str = str;

那麼本質上,也就是兩個指標指向一塊堆空間。已經違背了我們的初衷。那麼在程式結束的時候,兩個物件回收的時候,會呼叫自己的解構函式,釋放這塊記憶體空間,由於兩個物件要呼叫兩次,即delete兩次,就會出現錯誤!

所以,當類中有指標型別時,依靠預設的拷貝建構函式的方法,已經無法滿足我們的需求,必須定義一個特定的拷貝建構函式,即不僅可以進行資料的拷貝,也可以為成員分配記憶體空間,實現真正的拷貝,也叫做深拷貝,這就是深拷貝建構函式。

深拷貝建構函式實現:

include

include

using namespace std;

define PI 3.1415

class Circle { private: double R; char *str; public: Circle(double R,char *str); Circle(Circle &A); ~Circle(); double area(); double girth(); };

Circle::~Circle() { delete []str; cout<<"Call Destructor"<<endl; } Circle::Circle(Circle &A) { cout<<"Copy Constructor"<<endl; this->R = A.R; this->str = new char[strlen(A.str)+1]; strcpy(this->str,A.str); } Circle::Circle(double R,char *str) { cout<<"Constructor"<<endl; this->R = R; this->str = new char[strlen(str)+1]; strcpy(this->str,str); }

double Circle::area() { return PI*R*R; } double Circle::girth() { return 2*PI*R; } int main() {

Circle A(5,"NO.1 Old class");
Circle B(A);
return 0;

}

其實現原理與帶引數的建構函式類似,在賦值之前開闢足夠的記憶體空間,來真正完成完整的拷貝,這就是所謂的“深拷貝”。

請大家理解後上機實驗!

相關文章