我的測試代碼如下
#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出來的指針等變量時,一定要有深層複製構造函數,或者每次涉及複製構造的地方,都使用類對象的引用==。