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