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出来的指针等变量时,一定要有深层复制构造函数,或者每次涉及复制构造的地方,都使用类对象的引用==。

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