C++中含自定义指针成员的类B的operator=正确实现问询
嘿,这个问题的核心是要处理深拷贝——因为不管是类A还是类B都涉及动态内存分配,默认的浅拷贝会直接导致内存泄漏、重复释放这类经典坑。咱们一步步来解决:
正确实现类B的
operator=步骤 首先得先把类A的内存管理问题解决掉,毕竟B的成员是A的指针,A自身的动态内存没处理好,B的赋值肯定没法正确工作。
第一步:给类A补上深拷贝逻辑
A里有个动态分配的int* b数组,默认的拷贝行为只会复制指针地址(浅拷贝),导致多个A对象共享同一块内存,销毁时会重复释放。所以必须给A实现拷贝构造函数、赋值运算符和析构函数:
#include <algorithm> // 用于std::copy class A { int a; int* b; public: // 默认构造函数 A() : a(1), b(new int[20]) {} // 拷贝构造:深拷贝数组内容 A(const A& other) : a(other.a) { // 重新分配内存,再把原对象的数组内容复制过来 b = new int[20]; std::copy(other.b, other.b + 20, b); } // 赋值运算符:用拷贝交换惯用法,安全又简洁 A& operator=(A other) { // 传值参数自动触发拷贝构造 swap(*this, other); return *this; } // 析构函数:释放动态数组 ~A() { delete[] b; // 注意是delete[],对应数组的new[] } // 友元swap函数,用于拷贝交换 friend void swap(A& first, A& second) noexcept { using std::swap; swap(first.a, second.a); swap(first.b, second.b); } };
这里的关键细节:
- 拷贝构造里必须为新对象的
b重新分配内存,再复制原数组的每一个元素,而不是直接复制指针。 - 赋值运算符用了拷贝交换惯用法:传值的临时对象会先完成深拷贝,然后和当前对象交换成员,临时对象销毁时会自动释放当前对象原来的内存,还能自动处理自赋值的情况。
第二步:实现类B的operator=
现在A已经能正确处理深拷贝了,B的赋值逻辑就清晰了——我们需要让新的B对象拥有一个独立的、深拷贝后的A对象,而不是和原B共享同一个A指针:
class B { A* a; public: // 默认构造函数 B() : a(new A) {} // 拷贝构造函数:创建新的A对象(用A的拷贝构造深拷贝) B(const B& other) : a(new A(*other.a)) {} // 赋值运算符:同样用拷贝交换惯用法 B& operator=(B other) { swap(*this, other); return *this; } // 析构函数:释放A对象 ~B() { delete a; } // 友元swap函数 friend void swap(B& first, B& second) noexcept { using std::swap; swap(first.a, second.a); } };
解释一下:
- B的拷贝构造函数里,我们用
*other.a作为参数调用A的拷贝构造,创建一个全新的A对象,这样两个B对象的a指针指向完全独立的内存块。 - 赋值运算符同样用拷贝交换,传值的
other会先通过B的拷贝构造生成临时对象,交换后临时对象销毁时会自动释放原B的A对象,全程不用手动判断自赋值,非常安全。
额外建议:用智能指针简化内存管理
如果你的项目用C++11及以上标准,强烈推荐用std::unique_ptr或std::shared_ptr来管理动态内存,这样可以省去手动写析构、拷贝构造的麻烦:
#include <memory> #include <algorithm> class A { int a; int* b; public: A() : a(1), b(new int[20]) {} A(const A& other) : a(other.a), b(new int[20]) { std::copy(other.b, other.b + 20, b); } A& operator=(A other) { swap(*this, other); return *this; } ~A() { delete[] b; } friend void swap(A& first, A& second) noexcept { using std::swap; swap(first.a, second.a); swap(first.b, second.b); } }; class B { std::unique_ptr<A> a; // 用unique_ptr自动管理A的内存 public: B() : a(std::make_unique<A>()) {} // 拷贝构造:手动实现深拷贝(因为unique_ptr不支持默认拷贝) B(const B& other) : a(std::make_unique<A>(*other.a)) {} // 赋值运算符:利用A的赋值逻辑 B& operator=(const B& other) { if (this != &other) { *a = *other.a; } return *this; } // 析构函数不用写,unique_ptr会自动释放内存 };
如果允许多个B对象共享同一个A对象,换成std::shared_ptr会更省心,连拷贝构造和赋值都不用手动写。
内容的提问来源于stack exchange,提问作者I Radu
相关产品推荐
相关产品推荐

