c++析構函數delete位置訪問衝突問題

我的測試代碼如下

#include <iostream>
#include <cstring>
#include <string>
using namespace std;

class A{
 		char* ch;
	public:
		A(char * str){
			int len =strlen(str);
			 ch = new char[len];
			 strcpy(ch,str);
		}
		~A(){
			delete []ch;
		}
};

void fun(A a){};	//類A做形參
void main(){
	A b("abcd");
	fun(b);		
}

代碼運行時報如下錯誤:
在這裏插入圖片描述
經過我的苦苦思索,終於弄清楚了原因。
c++中使用一個對象對另一個對象進行初始化時,會調用類的複製構造函數,而複製構造函數又可分爲**深層複製和淺層複製**,對於前者,兩個對象之間是完全獨立的個體,只是二者的所有值都相等,而對於後者加粗樣式,兩者之間藕斷絲連,對於棧內存上的變量,二者分別有各自的內存,而對於堆內存上的變量,二者共用一塊內存,只不過使用不同的指針指向這塊地址。而默認的賦值構造函數是淺層複製的。
在此代碼中,main函數中的a對象當實參傳入函數時,會調用複製構造函數,此時,b與a共用一塊堆內存;當fun函數調用完成後,a被釋放,導致b中的char* 所指向的內存也被釋放掉了,從而當b的析構函數被調用是,無內存可以釋放,因此報錯。
解決方案:
①利用引用做形參

#include <iostream>
#include <cstring>
#include <string>
using namespace std;

class A{
 char* ch;
public:
	A(char * str){
		 int len =strlen(str);
		 ch = new char[len+1];
		 strcpy(ch,str);
	}
	~A(){
		delete []ch;
	}
};

void fun(A &a){};  //引用做實參
void main(){
	A a("abcd");
	fun(a);		
}

②重載複製構造函數爲深層構造函數

#include <iostream>
#include <cstring>
#include <string>
using namespace std;

class A{
 char* ch;
public:
	A(char * str){
		int len =strlen(str);
		 ch = new char[len+1];
		 strcpy(ch,str);
	}
	A(A& a){
		int len =strlen(a.ch);
		ch = new char[len+1];
		strcpy(ch,a.ch);
	}
	~A(){
		delete []ch;
	}
};

void fun(A a){};
void main(){
	A a("abcd");
	fun(a);		
}

== 總之,當類中有new出來的指針等變量時,一定要有深層複製構造函數,或者每次涉及複製構造的地方,都使用類對象的引用==。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章