运算符重载场景下结果为何不同?C++向量类技术问题
问题根源:缺失赋值运算符导致的浅拷贝与悬空指针
你的代码中,*C = *A + *B出现异常结果,而Vectors D = *A+*B正常,核心原因是只实现了拷贝构造函数,但未重载赋值运算符operator=,导致默认赋值执行浅拷贝,具体细节如下:
1. operator+的执行逻辑
你的operator+在堆上创建对象并返回:
Vectors operator+(const Vectors& obj1,const Vectors& obj2) { Vectors *res = new Vectors; // 计算向量加法 return *res; }
返回*res时,会调用你实现的拷贝构造函数生成一个临时栈对象,同时res指向的堆对象未被delete,已经造成内存泄漏。
2. *C = *A + *B的异常原因
这条语句是赋值操作,而非对象初始化:
*A + *B生成临时对象,其vector指向存储正确计算结果的堆内存- 由于未重载
operator=,编译器生成的默认赋值运算符会执行浅拷贝:直接将临时对象的vector指针值赋值给C->vector,而非重新分配内存复制数据 - 赋值完成后,临时对象被销毁,析构函数会
delete[] vector释放其内存,此时C->vector变成悬空指针 - 调用
C->print_vector()时,访问的是已被释放的内存,因此出现垃圾值
3. Vectors D = *A+*B正常的原因
这条语句是拷贝初始化,直接调用你实现的拷贝构造函数:
- 拷贝构造函数会重新分配一块独立的堆内存,逐一复制临时对象
vector中的数据 - 临时对象销毁后,D的
vector指向自身独立的内存,不受影响,因此打印结果正常
解决方案
方案1:重载赋值运算符,实现深拷贝
在Vectors类中声明并实现赋值运算符:
class Vectors { // 现有成员 public: Vectors& operator=(const Vectors& rhs); // 声明 }; // 实现 Vectors& Vectors::operator=(const Vectors& rhs) { // 防止自赋值 if (this == &rhs) return *this; // 释放当前对象的内存 delete[] vector; // 重新分配内存并复制数据 vector = new double[3]; for (int i = 0; i < 3; ++i) { vector[i] = rhs.vector[i]; } return *this; }
方案2:优化operator+,避免内存泄漏
原operator+中new的对象未被释放,会造成内存泄漏。可以直接创建栈对象返回,更高效安全:
Vectors operator+(const Vectors& obj1,const Vectors& obj2) { Vectors res; // 栈对象,默认构造初始化 for (int i = 0; i < 3; i++){ res.vector[i] = obj1.vector[i] + obj2.vector[i]; } return res; }
返回栈对象时,编译器通常会进行返回值优化(RVO),避免不必要的拷贝,性能更优。
额外建议
- 将
vector成员设为private,遵循封装原则,避免外部直接操作内部指针 - 可以用
std::array<double, 3>代替动态分配的数组,无需手动管理内存,编译器会自动生成正确的拷贝构造、赋值运算符和析构函数
内容的提问来源于stack exchange,提问作者Abhijit Baishya
相关产品推荐
相关产品推荐

