C++入门自学Day3-- c++类与对象(赋值运算符与拷贝构造)
C++内容往期回顾:
c++类与对象(拷贝构造)
c++类与对象(构造和析构函数)
c++类与对象(初识2)
c++类与对象(初识)
上期内容我们讲解了,有关于拷贝构造函数和一些运算符重载的实现,本节内容我们基于之前学习过的内容,讲解下一“赋值运算符”的作用,实现以及和拷贝构造函数的区别。
赋值运算符重载
定义形式:
把一个对象赋值给已存在的对象,而拷贝构造函数是用另一个对象初始化新对象。 |
注意是:已存在对象后再赋值:如 b = a;
默认行为:
-
C++ 自动提供一个默认的拷贝构造函数和赋值运算符重载;
-
它们都是浅拷贝(即只复制指针地址,而不是数据本身);
-
如果类中包含动态内存(new)或资源句柄,你应该显式定义这两个函数以避免资源冲突(如两次 delete
-
代码实现:
class Stack{public:Stack(int capacity = 10){_arr = (int*)malloc(sizeof(int)*capacity);cout<<"malloc "<<_arr<<endl;_size = 0;_capacity = capacity;};~Stack(){cout<<"free "<<_arr<<endl;free(_arr);_arr = nullptr;_size = 0;_capacity =0;};Stack(const Stack& s1){_arr = (int*)malloc(sizeof(int)*s1._capacity);cout<<"malloc"<<_arr<<endl;_size = s1._size;_capacity = s1._capacity;}Stack& operator =(const Stack& s1){if(this != &s1){for(int i = 0;i<s1._size;i++){_arr[i] = s1._arr[i];}cout<<" copy= "<<endl;_size = s1._size;_capacity = s1._capacity;}return *this;}private:int* _arr;int _size;int _capacity; };
主函数调用:
int main(){Stack s1;Stack s2(s1);s2 = s1; }
输出描述:
malloc 0x135204080
malloc0x1352040b0
copy=
free 0x1352040b0
free 0x135204080这里我们先使用拷贝构造定义了s2这个对象 分配内存地址为 0x137e05f40,然后我们又使用了赋值运算符把s1赋值给了s2, 输出 “copy=”,然后程序介绍清理内存。
拷贝构造和赋值运算符的区别
-
拷贝构造函数:负责深拷贝分配新资源
-
赋值运算符重载:
-
必须检查是否是自赋值(if (this == &other) return *this;)
-
先释放原有资源,再拷贝新资源。
-
比较项 | 拷贝构造 | 赋值重载 |
---|---|---|
新对象? | ✅ 是 | ❌ 否 |
旧资源需释放? | ❌ 不需要 | ✅ 需要 |
常见错误 | 没有定义时默认浅拷贝 | 忘记释放旧资源、自赋值处理 |
是否可连用? | 不适用 | ✅ 可连用 (a = b = c) |
深拷贝和浅拷贝的区别
浅拷贝只复制指针的地址(两对象指向同一块资源);深拷贝则复制指针指向的内容(资源独立)。
拷贝构造函数和赋值运算符重载都是实现复制的工具,它们都可以实现浅拷贝或深拷贝。
🔸 浅拷贝(Shallow Copy)
-
复制指针本身,多个对象指向同一块内存。
-
修改一个对象的数据,会影响另一个。
-
释放内存时,可能发生 重复释放(double free) 错误。
🔸 深拷贝(Deep Copy)
-
不仅复制指针,还复制指针指向的数据,每个对象拥有独立内存。
-
资源安全,彼此互不影响。
-
推荐用于资源管理类(如有 new 的类)。
深/浅拷贝 和 拷贝构造/赋值重载 的关系
概念 | 是什么 | 是否控制深浅拷贝? | 默认行为 |
---|---|---|---|
拷贝构造函数 | 用一个对象初始化新对象 | ✅ 可以深也可以浅(你决定怎么写) | 默认是浅拷贝 |
赋值运算符重载 | 把一个对象赋值给已有对象 | ✅ 同上 | 默认是浅拷贝 |
浅拷贝 | 只复制地址,不复制内容 | ❗危险,资源冲突风险 | 编译器默认行为 |
深拷贝 | 复制地址+复制内容 | ✅ 安全,资源独立 | 必须手动实现 |
总结归纳
-
拷贝构造函数 → “出生时复制”
-
赋值运算符重载 → “成长中替换”
-
如果你的类涉及动态分配内存、文件句柄、网络资源等,必须自己写这两者,否则会出现资源泄漏或重复释放。
概念 | 功能 | 默认实现 | 是否复制指针内容 | 会不会内存冲突 |
---|---|---|---|---|
拷贝构造 | 新建时复制 | 默认浅拷贝 | ❌ | 可能会 |
赋值运算符 | 已存在对象被赋值 | 默认浅拷贝 | ❌ | 可能会 |
浅拷贝 | 复制指针地址 | 是 | ❌ | ✅ 有风险 |
深拷贝 | 复制指针内容 | 否,需要自写 | ✅ | ❌ 安全 |