淺拷貝
是棧區(qū)中的對象引用都是指向同一個堆區(qū)的空間內(nèi)存。
注意:此時棧區(qū)的對象多次被釋放,引發(fā)同一個內(nèi)存地址重復(fù)釋放的錯誤。
深拷貝
在堆區(qū)開辟多個內(nèi)存空間,讓賦值的引用對象指向不同的堆區(qū)內(nèi)存地址。
場景如下
A、棧區(qū)中,子函數(shù)return 對象,進(jìn)行賦值操作;B、棧區(qū)中,傳遞對象給子函數(shù)進(jìn)行傳遞引用。
注:默認(rèn)的拷貝構(gòu)造函數(shù)里使用的是淺拷貝:在棧區(qū)先構(gòu)建新地址,然后進(jìn)行賦值。
//存在類 Student
class Student{
Student(){}
Student(char * name){
// TODO: name成員屬性在堆內(nèi)存開辟空間了
this->name = (char *)malloc(sizeof(char * 10));
strcpy(this->name,name);
}
Student(const Student & stu){
//自定義拷貝構(gòu)造函數(shù)
//3、TODO:深拷貝: 給在堆區(qū)的成員屬性,重新開辟內(nèi)存空間
this->name = (char *)malloc(sizeof(char * 10)); //name成員屬性在堆內(nèi)存開辟空間了
strcpy(this->name,name);
}
};
Student getStudent(){
Student stu("name");
return stu;
}
Student setStudent(Student stu){
count<< &stu<< endl;
}
void main(){
// 1、 此 = 等號賦值操作程序執(zhí)行流程:1、getStudent子函數(shù)里先執(zhí)行Student的構(gòu)造函數(shù),然后執(zhí)行拷貝構(gòu)造函數(shù)返回棧區(qū)中新的地址引用給stu1,最后getStudent彈棧調(diào)用析構(gòu)函數(shù)釋放舊地址;
Student stu1 = getStudent();
// 2、此 參數(shù)傳遞 操作程序執(zhí)行流程:1、stu2先執(zhí)行Student的構(gòu)造函數(shù),然后執(zhí)行拷貝構(gòu)造函數(shù)返回棧區(qū)中新的地址引用給setStudent,最后setStudent彈棧調(diào)用析構(gòu)函數(shù)釋放新地址;
Student stu2;
setStudent(stu2);
}
以上代碼案例,若拷貝構(gòu)造函數(shù)中不進(jìn)行深拷貝,則在mian函數(shù)中 student對象多次賦值,程序執(zhí)行后,setStudent()彈棧、main()彈棧時都會出現(xiàn)同一個內(nèi)存被釋放多次的錯誤;
總結(jié):一旦成員屬性涉及堆內(nèi)存空間,一定需要深拷貝。
問題bug:多次重復(fù)釋放同一內(nèi)存地址的錯誤的;解決方法:對于在堆區(qū)的成員屬性,在自定義拷貝構(gòu)造函數(shù)中重新開辟內(nèi)存地址,如:
this->name = (char *)malloc(sizeof(char * 10));
strcpy(this->name,name);