您好,登錄后才能下訂單哦!
對(duì)于一般的對(duì)象,如:
int a = b;
int c = 5;
它們之間的賦值,復(fù)制很簡(jiǎn)單,到對(duì)于類對(duì)象來說,其內(nèi)部存在各種成員變量,他的復(fù)制,賦值就不是如此的簡(jiǎn)單,如果處理不當(dāng),就會(huì)出現(xiàn)各種問題。
我們首先來看一下下面的代碼:
#include<iostream>
using namespace std;
#include<string.h>
class String
{
public:
String(const char* ptr)
:_ptr(new char[strlen(ptr) + 1])
{
strcpy(_ptr, ptr);
cout << "String" << endl;
cout << _ptr << endl;
}
String(const String& ptr)
:_ptr(ptr._ptr)
{}
String& operator=(const String& ptr)
{
if (this != &ptr)
{
_ptr = ptr._ptr;
}
return *this;
}
~String()
{
cout << "~String" << endl;
delete[] _ptr;
}
private:
char * _ptr;
};
void Test()
{
String s("hello");
String s2(s);
}
int main()
{
Test();
return 0;
}
可以看到,這里對(duì)同一對(duì)象析構(gòu)了兩次,我們通過下面的圖來對(duì)這個(gè)現(xiàn)象進(jìn)行解釋:
在進(jìn)行對(duì)象復(fù)制后,事實(shí)上s、s2里的成員指針_ptr都指向了一塊內(nèi)存空間(即內(nèi)存空間共享了),在s1析構(gòu)時(shí),delete了成員指針_ptr所指向的內(nèi)存空間,而s2析構(gòu)時(shí)同樣指向(此時(shí)已變成野指針)并且要釋放這片已經(jīng)被s1析構(gòu)函數(shù)釋放的內(nèi)存空間,這就讓同樣一片內(nèi)存空間釋放了兩次 ,從而出錯(cuò)。而淺拷貝還存在著一個(gè)問題,因?yàn)橐黄臻g被兩個(gè)不同的子對(duì)象共享了,只要其中的一個(gè)子對(duì)象改變了其中的值,那另一個(gè)對(duì)象的值也跟著改變了。
在這里呢我們找到了深拷貝來解決這個(gè)問題。
下面是深拷貝的拷貝構(gòu)造函數(shù)代碼:
String(const String& ptr)
:_ptr(new char[strlen(ptr._ptr) + 1])
{
strcpy(_ptr, ptr._ptr);
}
這里通過重新開辟一段空間來解決淺拷貝中析構(gòu)兩次的情況。
在淺拷貝中還存在其他的一些問題,比如賦值運(yùn)算符重載,他也是s,s1,兩個(gè)對(duì)象指向同一塊內(nèi)存空間。在析構(gòu)時(shí)同樣會(huì)出現(xiàn)問題。還有析構(gòu)函數(shù),如果這塊空間為NULL,又怎么能進(jìn)行析構(gòu)呢!
我們給出深拷貝的函數(shù)代碼:
class String
{
public:
String(const char* ptr)
:_ptr(new char[strlen(ptr) + 1])
{
strcpy(_ptr, ptr);
}
String(const String& ptr)
:_ptr(new char[strlen(ptr._ptr) + 1])
{
strcpy(_ptr, ptr._ptr);
}
String& operator=(const String& ptr)
{
if (this != &ptr)
{
delete[] _ptr;
char* tmp = new char[strlen(ptr._ptr) + 1];
strcpy(tmp, ptr._ptr);
_ptr = tmp;
}
return *this;
}
~String()
{
if (_ptr)
{
delete[] _ptr;
}
}
private:
char* _ptr;
};
void Test()
{
String s("hello");
String s2(s);
String s3("11111");
s3 = s;
}
int main()
{
Test();
return 0;
}
通過深拷貝我們就能解決淺拷貝的問題。
對(duì)深拷貝中的賦值運(yùn)算符重載我們做以下說明:
1.進(jìn)入賦值運(yùn)算符重載,我們首先需要判斷該對(duì)象是不是自己給自己賦值,自己給自己賦值從賦值上來說也沒錯(cuò),但是在調(diào)用析構(gòu)函數(shù)時(shí)又怎該去析構(gòu)呢?不是又給同一對(duì)象析構(gòu)兩次嗎?
2.賦值運(yùn)算符重載的深層理解
String& operator=(const String& ptr)
s3 = s;
賦值運(yùn)算符重載傳參是其實(shí)是這樣的:s3.operator=(&s3,s),&s3其實(shí)就是this指針,在實(shí)現(xiàn)賦值運(yùn)算符重載的過程中,首先析構(gòu)掉s3原本空間的內(nèi)容,然后開辟一段新空間,把s的內(nèi)容復(fù)制到新空間中,再把新空間的內(nèi)容給給s3,完成賦值。
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。