新对象赋值至已有对象地址时需销毁原对象吗?及相关代码疑问
问题解答:对象赋值时原对象的销毁与内存问题
先看你的代码和输出,核心问题在于你误解了赋值操作和对象销毁的区别,我们逐个拆解你的疑问:
1. 为什么Thing 0看起来没被销毁?
其实它已经被销毁了,只是你认不出它了😉。具体原因:
- 当执行
c.at(0) = thing();时,你创建了一个临时thing对象(Thing 2),C++的默认赋值运算符会把这个临时对象的id成员拷贝给原有的Thing 0——这时候原Thing 0的id已经被覆盖成2了。 - 当容器
c的析构函数执行delete[] this->things时,会销毁数组里的两个thing对象:第一个是被修改了id的原Thing 0(现在id是2),所以打印Thing 2 destroyed;第二个是原Thing 1,打印Thing 1 destroyed。
你看到的最后那个Thing 2 destroyed,就是原Thing 0被销毁时的输出——只是它的id已经被临时对象覆盖了。
2. 是否存在内存泄漏?
完全没有。容器的析构函数正确调用了delete[] this->things,这会自动销毁整个thing数组,包括数组里的两个对象(原Thing 0和Thing 1),所有通过new[]分配的内存都被正确释放了。
3. 是否需要手动销毁Thing 0?
不需要。你不需要手动销毁单个数组元素——delete[]会自动处理数组中所有对象的析构和内存释放。如果你尝试手动销毁c.at(0)对应的对象,反而会导致重复释放内存,引发未定义行为。
额外解释:为什么Thing 2被销毁两次?
- 第一次:临时对象
thing()创建后,完成赋值操作就会被销毁(临时对象的生命周期只到当前语句结束),所以打印Thing 2 destroyed。 - 第二次:原Thing 0被赋值后id变成2,容器销毁时它被销毁,再次打印
Thing 2 destroyed。
如果你想验证原Thing 0确实被修改了,可以给thing类加一个赋值运算符重载,打印赋值过程:
thing& operator=(const thing& other) { printf("Thing %zd assigned to Thing %zd\n", other.id, this->id); this->id = other.id; return *this; }
加上后你会看到输出里多一行:Thing 2 assigned to Thing 0,就能直观看到赋值过程了。
内容的提问来源于stack exchange,提问作者sanitizedUser
相关产品推荐
相关产品推荐

