![](/img/trans.png)
[英]Is the previous object destroyed when the variable holding it gets assigned a new one using a copy constructor?
[英]Does object have to be destroyed when a new object is assigned to its address?
考虑以下代码。
#include <stdio.h>
using namespace std;
constexpr size_t TOTAL = 2;
class thing
{
private:
inline static size_t NEXT_ID = 0;
size_t id;
public:
thing() : id(NEXT_ID++)
{
printf("Thing %zd created.\n", this->id);
}
~thing()
{
printf("Thing %zd destroyed.\n", this->id);
}
};
class container
{
private:
inline static size_t NEXT_ID = 0;
size_t id;
thing* things;
public:
container() : id(NEXT_ID++)
{
this->things = new thing[TOTAL];
printf("Container %zd created.\n", this->id);
}
~container()
{
delete[] this->things;
printf("Container %zd destroyed.\n", this->id);
}
thing& at(size_t idx) // this is the important method
{
return this->things[idx];
}
};
int main()
{
container c;
c.at(0) = thing(); // here is the problem
return 0;
}
output 是我没想到的。
Thing 0 created.
Thing 1 created.
Container 0 created.
Thing 2 created.
Thing 2 destroyed.
Thing 1 destroyed.
Thing 2 destroyed.
Container 0 destroyed.
我知道Thing 2
是一个临时的 object,这就是它被摧毁两次的原因。 关于Thing 0
发生的事情,我有几个问题。
Thing 0
没有被摧毁?Thing 0
还是成功覆盖? 没有对同一个 object 的析构函数的双重调用。 问题仅出在您的 output 中。 您正在打印id
但c.at(0) = thing();
中的副本分配将临时 object 中的id
复制到容器中的那个。 这就是你看到两个“事物 2 被摧毁”的原因。 并且没有“Thing 0 被破坏。”。
如果您想要更好的日志记录机制,您可以打印this
指针。 object 的地址在 object 的生命周期内不会改变,它是 object 的唯一标识符。 当然,为方便起见,您还可以打印id
。
printf("Thing %p %zd created.\n", static_cast<void*>(this), this->id);
printf("Thing %p %zd destroyed.\n", static_cast<void*>(this), this->id);
这应该会给你一些像这样的 output (当然 0x11111111、0x22222222 和 0x33333333 在你的情况下看起来会有所不同):
事物 0x11111111 0 已创建。
事物 0x22222222 1 已创建。
容器 0 已创建。
事物 0x33333333 2 已创建。
东西 0x33333333 2 被破坏。
东西 0x22222222 1 被破坏。
东西 0x11111111 2 被破坏。
容器 0 被破坏。
在这份声明中
c.at(0) = thing();
这里使用了由编译器复制赋值运算符隐式定义的。 因此,由表达式c.at(0)
引用的 object 的数据成员id
变为等于由表达式thing()
创建的临时2
的 ID。
在此语句中,临时 object 被创建并最终被销毁
Thing 2 created.
Thing 2 destroyed.
现在 object c
包含两个作为数组元素存储thing
子对象。 子对象具有 id(s) 2
和1
。
它们以与创建它们相反的顺序被删除
Thing 1 destroyed.
Thing 2 destroyed. // previously it has id equal to 0
所以程序没有 memory 泄漏。 从程序 output 可以看出,所有创建的对象都已成功删除。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.