天天看點

C++面向對象程式設計,深淺拷貝

作者:黑貓程式設計

深淺拷貝

編譯器預設提供的拷貝是淺拷貝,将一個對象中所有成員變量的值拷貝到另一個對象。

然而,如果某個對象成員是指針類型,隻會拷貝指針中存儲的位址值,并不會拷貝指針指向的記憶體空間。

當通過構造函數指派時,類外部指針和類内部指針指向同一塊記憶體空間,會互相幹擾。

class Student {
private:
	char* m_name;
	int m_age;
public:
	Student(char* name, int age):m_name(name),m_age(age){}
	void output() {
		cout << m_name << " " << m_age << endl;
	}
	void changeName() {
		m_name[0] = 'x';
	}
};           
int main() {
	char name[10] = "blackcat";
	Student* stu1 = new Student(name, 10);
	stu1->output();
	cout << name << endl;

	stu1->changeName();

	stu1->output();
	cout << name << endl;
	return 0;
}           
C++面向對象程式設計,深淺拷貝

不僅兩個指針可以互相修改記憶體資料,棧空間資料很可能會釋放,導緻堆空間指向資料消失。

解決方案

在堆空間再開辟一塊記憶體,把棧空間資料拷貝過來,防止互相幹擾。

Student(char* name, int age){
	m_name = new char[strlen(name) + 1]();
	strcpy(m_name, name);
	m_age = age;
}

~Student() {
	if (m_name == NULL) return;
	delete[] m_name;
	m_name = NULL;
}           
C++面向對象程式設計,深淺拷貝

拷貝構造問題

在堆空間備份棧空間資料,可以起到指針變量指派時進行資料隔離。

然而,如果遇到拷貝構造會出現什麼問題呢?

如果成員變量是指針類型,拷貝構造會導緻多個對象儲存同一個指針,不同對象的指針指向同一塊記憶體空間,是以可以互相修改,并且析構時,會對同一塊記憶體空間進行多次析構,使得程式發生異常。

C++面向對象程式設計,深淺拷貝

析構釋放時會出現 double free 情況。

深拷貝

将原指針指向的記憶體空間拷貝一份到新的空間。

C++面向對象程式設計,深淺拷貝
private:
	char* m_name;
	int m_age;

	void copyName(const char* name) {
		if (name == NULL) return;
		m_name = new char[strlen(name) + 1]();
		strcpy(m_name, name);
	}           
public:
	Student(const char* name, int age) {
		copyName(name);
		m_age = age;
	}

	Student(const Student& stu) {
		copyName(stu.m_name);
		m_age = stu.m_age;
	}           

繼續閱讀