如何实现类运算符不创建新对象?解决对象重复析构问题
为什么你的对象会被析构两次?如何优化运算符重载?
嘿,我来帮你拆解这个问题!首先看你代码里的operator+=实现,这里藏着导致两次析构的关键:
myint operator += (int const &y) { this->x += y; return y;}
你返回的是y(一个int),但函数的返回类型是myint——这会触发隐式类型转换:编译器会调用你的myint(int x)构造函数,把int y转换成一个临时的myint对象。这个临时对象在i +=3这条语句执行完后就会被销毁,加上main函数结束时对象i的析构,自然就输出了两次DEL。
如何修复并优化?
针对你的需求(不创建新对象、优化大型对象操作),我们需要遵循复合赋值运算符的标准实现惯例:
1. 让operator+=返回自身的引用
复合赋值运算符(比如+=、-=)的设计初衷就是修改当前对象,然后返回对象本身的引用,这样既不会生成临时对象,还支持链式调用(比如i +=3 +=5)。
修正后的代码如下:
#include <iostream> using namespace std; class myint{ public: int x; myint(int x) { this->x = x;} ~myint() {cout << "DEL" << endl; } // 修改返回类型为myint&,返回*this myint& operator += (int const &y) { this->x += y; return *this; } }; int main() { myint i = myint(2); i += 3; }
现在运行代码,只会输出一次DEL——因为不再生成临时对象,只有main里的i被析构。
2. 额外优化:避免不必要的拷贝(针对大型对象)
如果你的类持有大型资源(比如动态数组、大内存块),还需要注意:
- 确保你的类有正确的拷贝构造函数和移动构造函数(如果需要拷贝的话),但对于
operator+=来说,返回引用已经避免了拷贝操作,完全符合你的优化需求。 - 如果你不需要拷贝对象,可以把拷贝构造函数和赋值运算符声明为
delete,防止意外的拷贝:myint(const myint&) = delete; myint& operator=(const myint&) = delete;
补充:运算符重载的最佳实践
- 复合赋值运算符(
+=、-=、*=等):返回*this的引用,不生成新对象。 - 二元运算符(
+、-、*等):通常返回临时对象(或者用移动语义优化),因为它们不修改原有对象,而是返回新的计算结果。比如myint operator+(const myint& other) const { return myint(x + other.x); }。
这样修改后,你的代码既解决了两次析构的问题,又能高效处理大型对象,完全符合你的需求!
内容的提问来源于stack exchange,提问作者Jake B.
相关产品推荐
相关产品推荐

