c++编译器至少给一个类添加4个函数
赋值运算符为什么需要深拷贝
赋值运算符(例如在许多编程语言中使用的 = 符号)通常用于将一个变量的值复制给另一个变量。在许多情况下,这种赋值操作执行的是浅拷贝,即只复制对象的引用而不复制对象本身。这意味着两个变量实际上引用同一个对象,而不是创建原始对象的副本。
然而,在某些情况下,特别是当涉及到可变对象时,浅拷贝可能会导致问题。这是因为对一个变量的修改可能会影响到另一个变量,因为它们引用的是同一个对象。这就是为什么有时候需要使用深拷贝。
深拷贝是一种创建目标对象的完全独立副本的方法,而不是仅仅复制引用。这样,即使对原始对象进行了修改,深拷贝创建的对象也不会受到影响。深拷贝通常涉及递归地复制对象的所有嵌套对象,确保原始对象及其所有嵌套结构的完整复制。
以下是为什么需要深拷贝的一些常见情况:
可变对象的问题: 如果对象包含可变子对象(例如列表、字典等),浅拷贝将只复制引用,导致对一个对象的修改影响到另一个对象。
避免共享状态: 在多线程或并发编程中,深拷贝可以用于创建每个线程独立的状态,避免多个线程共享相同的对象状态。
防止副作用: 当对一个对象的操作会对其他对象产生意外副作用时,使用深拷贝可以避免这种情况。
在许多编程语言中,库或框架通常提供深拷贝的实现,程序员可以选择使用深拷贝以确保在不同变量之间创建独立的对象。
- 默认构造函数(无参,函数体为空)
- 默认析构函数(无参,函数体为空)
- 默认拷贝构造函数,对属性进行值拷贝
- 赋值运算符 operator=, 对属性进行值拷贝
如果类中有属性指向堆区,做赋值操作时也会出现深浅拷贝问题
#include<iostream>
using namespace std;
class Person {
public:
Person(int age) {
//将年龄数据开辟到堆区
m_Age = new int(age);
}
//重载赋值运算符
Person& operator=(Person& p)
{
//应该先判断是否属性再堆区,如果有先释放干净,然后再深拷贝
if (m_Age != NULL)
{
delete m_Age;
m_Age = NULL;
}
//编译器提供的代码是浅拷贝
//m_Age = p.m_Age;
//提供深拷贝 解决浅拷贝的问题
m_Age = new int(*p.m_Age); //*p.m_Age
//返回自身
return *this; //this =Person operator=
}
~Person()
{
if (m_Age != NULL)
{
delete m_Age;
m_Age = NULL;
}
}
int *m_Age;
};
void test01()
{
Person p1(18);
Person p2(20);
Person p3(30);
p3 = p2 = p1; //赋值
cout << "p1的年龄为:" << *p1.m_Age << endl;
cout << "p2的年龄为:" << *p2.m_Age << endl;
cout << "p3的年龄为:" << *p3.m_Age << endl;
}
int main()
{
//test01();
test01();
return 0;
}