C++深淺拷貝
阿新 • • 發佈:2021-01-28
淺拷貝:簡單的賦值拷貝操作。當指標進行淺拷貝時可能會導致多個物件共用同一記憶體資源,同一塊記憶體資源釋放多次,導致崩潰或者記憶體洩漏,
深拷貝:在堆區中重新申請空間,進行拷貝操作。
例證:
#include<iostream>
using namespace std;
class Person
{
public:
int age;
int* height;
Person()//無參建構函式
{
age = 19;
height = new int(169);
}
~Person()//解構函式,其作用可以用來釋放堆區的資料
{
if (height != NULL)
{
delete height;
height = NULL;
}
}
};
int main()
{
Person p;
Person q(p);
system("pause");
}
程式執行會出錯
編譯器會提供一個預設的拷貝建構函式:
Person(const Person &p)
{
age = p.age;
height = p.height;
}
“height = p.height;”這一句為簡單的賦值操作,進行了淺拷貝,因此q的height指標與p的height指標會指向同一個記憶體空間,在程式結束前需要呼叫各自的解構函式,由於棧的特點,先呼叫q的析構,它的height指標不為空,因此會釋放它所指向的空間,再呼叫p的解構函式,這裡出現了問題,由於p的height指標不為空(其實是野指標了),因此需要釋放其所指的記憶體空間,此空間在q的解構函式中已經被釋放了,再次釋放未非法操作,因此程式出錯。
要解決此等錯誤,就要使得兩指標指向不同的記憶體,因此需要我們自己提供拷貝建構函式:
Person(const Person &p)//拷貝建構函式
{
age = p.age;
height = new int(*p.height);
}
這樣p和q的指標都指向堆中不同記憶體單元,程式執行無誤。
在寫程式時,儘量避免多個指標指向同一個記憶體單元。
補:
預設情況下,編譯器會給一個類提供三個函式:無參建構函式(函式體為空)、解構函式(函式體為空)、拷貝建構函式(對各屬性進行值拷貝)
如果程式設計師提供了有參建構函式,則編譯器不再提供無參建構函式,但會提供解構函式和拷貝建構函式。