前言
本系列内容为程序媛学习C++时做的笔记。以代码为主,并备注了打印结果以及详尽的解释注释。希望对你有所帮助。
深拷贝/浅拷贝
举例1
#include<iostream>
#include<string.h>
using namespace std;
class Student2 {
public:
int age;
char *name;
Student2() { cout << "空参数构造函数" << endl; }
Student2(char *name) : Student2(name, 99) {
cout << "一个参数构造函数 this:" << this << endl;//2
}
Student2(char *name, int age) {
cout << "二个参数构造函数 this:" << this << endl;//1
this->name = (char *) malloc(sizeof(char *) * 10);
strcpy(this->name, name);
this->age = age;
}
~Student2() {
cout << "析构函数执行 &this->name:" << &this->name << endl;//5
free(this->name);
this->name = NULL;
}
// 默认有一个拷贝构造函数 隐士的 我们看不见
// 一旦复写了拷贝构造函数,默认的还在吗? Java的构造函数一个思路
Student2(const Student2 &stu) {
// stu 是旧地址 // this 是新地址
cout << "拷贝构造函数 &stu:" << &stu << " this:" << this << endl;//4
// 新地址name = 旧地址 (浅拷贝,见注意)
this->name = stu.name;
} // 此拷贝构造函数执行完 就会出现一个 this==新地址 给 main函数的 stu
};
Student2 getStudent(char *name) {
Student2 stu(name); // 旧地址
cout << "getStudent函数:" << &stu << endl; // 旧地址//3
return stu; // stu 旧地址
} // 弹栈 释放 栈成员 stu
int main() {
// = 会执行拷贝构造函数
// stu 新地址
Student2 stu = getStudent("截拳道");
cout << "main函数:" << &stu << endl;//6
// getchar(); // 不要一闪而过,让程序停留
return 0;
} // main函数弹栈 stu 新地址 析构函数执行
执行流程打印:
举例2
void showStudent(Student stu) {//stu 新地址 这里的入参stu会执行拷贝构造函数 //2
cout << "showStudent函数:" << (int)&stu << " " << stu.name << "," << stu.age<< endl;//新地址 //3
}
void main() {
Student stu("刘奋", 31);//stu旧地址 //1两个参数构造函数
showStudent(stu); // 弹栈后 新地址name释放一遍 //4
// showStudent(stu); // 弹栈后 新地址name释放一遍
// 两次释放新地址name 会奔溃
// 释放一次新地址name 再释放一次旧name也报错
getchar();
} // main函数弹栈 stu 旧地址
注意:
// 【浅拷贝】:新地址name 旧地址name 指向同一个空间,会造成,重复free的问题,引发奔溃
// 新地址name = 旧地址 (浅拷贝)
// this->name = stu.name;
默认的拷贝是浅拷贝。
// 【深拷贝】两个name分别指向不同的堆空间。重复free就不会报错。
this->name = (char *)malloc(sizeof(char *)* 10);
strcpy(this->name, name);