浅拷贝
类名(const 类引用 变量)
{
//拷贝构造的函数体:
//拷贝的逻辑
}
编译器会提供一个简单的值的拷贝
弊端:当类中有指向堆区的指针时,浅拷贝会将新旧两个对象都指向堆区同一片空间。这样会造成资源冲突,以及析构的时候,会两次释放
当遇到此情况时,须升级浅拷贝为深拷贝。
浅拷贝验证:
类代码
#include <iostream>
#include <cstdio>
using namespace std;
class Stu
{
private:
string name;
int age;
int *p;
public:
//构造
Stu(string name, int age)
{
this->name = name;
this->age = age;
this->p = new int[1024]();
cout << this->name << "的构造" << endl;
}
//拷贝
Stu (const Stu& other)
{
cout << this->name << "的拷贝" << endl;
//浅拷贝
this->name = other.name;
this->age = other.age;
this->p = other.p;
//浅拷贝会将两个类的指针类型,指向同一片地址,
//这样会造成资源冲突,以及析构的时候,会两次释放
}
//析构
~Stu()
{
delete [] p;
cout << this->name << "的析构" << endl;
}
string getname()
{
return this->name;
}
int getage()
{
return this->age;
}
int * shoup(){
return this->p;
}
void showInfo()
{
cout << "姓名:" << this->name << ",年龄:" << this->age << endl;
}
};
主函数:
int main()
{
Stu stu1("zhangsan", 18);
stu1.showInfo();
Stu stu2("lisi", 20);
stu2.showInfo();
//调用类构造方法拷贝
Stu stu3(stu1);
stu3.showInfo();
//(改造深拷贝之前)打印stu1和stu3的p值,看是否相同
//结果相同,证明浅拷贝对指针地址用的同一片空间
printf("stu1.p=%#x\n", stu1.shoup());
printf("stu3.p=%#x\n", stu3.shoup());
}
运行结果:
深拷贝
在拷贝构造方法中,开辟同样大小的堆区空间,使用memmove函数,复制一份数据到该堆区空间。
深拷贝验证:
类代码(沿用上边类代码,更改拷贝构造方法):
//拷贝
Stu (const Stu& other)
{
cout << this->name << "的拷贝" << endl;
//浅拷贝
this->name = other.name;
this->age = other.age;
this->p = other.p;
//浅拷贝会将两个类的指针类型,指向同一片地址,
//这样会造成资源冲突,以及析构的时候,会两次释放
//深拷贝
this->p = new int[1024];
memmove(this->p, other.p, sizeof (int[1024]));
cout << "Stu的拷贝构造" << endl;
}
沿用上边主函数,运行结果:
发现两个对象的属性指针所指堆区的地址不同。
拷贝构造调用时机
1.使用其他已经生成的对象为本对象进行初始化。
2.当函数形参为类类型,默认发生拷贝构造
3.当函数返回值为类类型,默认发生拷贝构造。
4.在函数传参或返回时,为了避免无意义的拷贝,提高函数的运行效率,推荐大家使用引用。