gpt4 book ai didi

C++ 析构函数调用了错误的对象?

转载 作者:太空宇宙 更新时间:2023-11-04 15:30:36 25 4
gpt4 key购买 nike

我是 C++ 新手,我编写了一个小程序来了解赋值如何处理对象。此页面 ( http://www.cplusplus.com/doc/tutorial/classes2/ ) 的 cpp 文档提示我执行此操作。在此页面上,它指出:

The implicit version [of the copy assignment operator] performs a shallow copy which is suitable for many classes, but not for classes with pointers to objects they handle its storage. In this case, not only the class incurs the risk of deleting the pointed object twice, but the assignment creates memory leaks by not deleting the object pointed by the object before the assignment.

我以粗体显示的最后一部分是我决定进行测试的原因。我认为这个问题可以通过在析构函数(这是标准的?)中处理指向对象的删除来解决,而不是必须重载复制赋值运算符。如果不调用析构函数,那不是很不方便吗?假设我有多个引用对象,我必须将所有删除都放在析构函数(对于大多数重新分配的情况)和赋值重载中。

在这次测试中,我遇到了一个完全不同的问题。我最初的想法是创建一个简单的类,它存储一个 int(作为用于测试目的的标识符)并重载构造函数和析构函数以查看何时以及是否调用了析构函数。

这是我的代码:

class Test{
public:
int id;
explicit Test(int id) : id(id) {
cout << "Created " << id << endl;
}
~Test() {
cout << "Destroyed " << id << endl;
}
};

int main() {
Test x = Test(1);
x = Test(2);

cout << x.id << endl;
return 0;
}

我期望的输出是:

1:创建 1
2: 销毁 1 ? (这是我不确定的,因为网站暗示如果对象被另一个对象“替换”而不是超出范围,则不会调用此析构函数)
3: Created 2 对象 2“替换”对象 1,因为它被分配给 x
4: 2打印出对象2的id值
5: Destroyed 2 对象 2 在超出范围时被销毁

相反,我得到了以下输出:

Created 1
Created 2
Destroyed 2
2
Destroyed 2

这对我来说真的没有意义。

使用调试器,Created 2Destroyed 2 都在调用行 x = Test(2); 时显示。如果我们刚刚将 x 分配给对象 2,为什么它的析构函数会立即被调用?接下来是下一部分。

其次,由于对象 2 的析构函数已被调用,我们可以假设它已被销毁。 2 的下一个输出似乎与此相矛盾,因为它表明 x 仍持有对象 2(预期,但与其析构函数的调用相矛盾)。

我不太清楚为什么会这样。

最后输出Destroyed 2。如果我们没有更早地看到这一点,这将是有道理的。对象 2 存储在 x 中,因此当它超出范围时,将调用析构函数。

由于某种原因,我们的析构函数被调用了两次,对象 1 被对象 2 赋值给 x 的对象“覆盖”了,它的析构函数从未被调用,而是对象的析构函数被调用我们刚刚创建的调用了它的析构函数。

所以...这总结为一个由两部分组成的问题:

1:为什么会出现这种奇怪的行为,是否有任何合乎逻辑的原因?
2:通过赋值用另一个对象(对象 2)“覆盖”一个对象(例如对象 1)是否会导致其析构函数(在本例中为对象 1 的析构函数)被调用?

提前致谢。

最佳答案

Using the debugger, Created 2 and Destroyed 2 both display when the line x = Test(2); is called. If we just assigned x to Object 2, why is its destructor being called immediately? This follows on to the next part.

x = Test(2); 首先创建一个带有构造函数参数 2Test。这就是生成 Created 2 的原因。这个无名的 Test 然后被分配给 x ,它给 x.id 值 2。那个无名的 Test 然后是destroyed 在表达式的末尾,产生“Destroyed 2”。

Secondly, since the destructor for Object 2 has been called, we can assume it has been destroyed. The next output of 2 seems to contradict this, as it suggests that x is still holding Object 2 (expected, but contradicted by the call of its destructor).

如本答案第一部分所述,被破坏的不是 x,而是临时 Tempx.id 仍然有效并将产生新值 2。

Finally, Destroyed 2 is outputted. This would make sense if we didn't see this earlier. Object 2 is stored in x, so when it goes out of scope the destructor is called.

x 在函数结束时被销毁时会发生这种情况。它的 id 值被之前的赋值更改为 2,因此它生成“Destroyed 2”。

1: Why is this weird behaviour occurring, and is there any logical reason to why it is?

这可能不是您预期的行为,但并不奇怪。我希望这个答案能帮助您理解为什么会发生这种情况。

2: Does 'overriding' an object (e.g. Object 1) with another object (Object 2) by assignment lead to its destructor (in this case the destructor of Object 1) to be called or not?

分配给一个对象并不会破坏它。它用一个新的值替换它的值,从这个意义上说,它“破坏”了它以前帮助过的,但实际的对象实例没有被破坏,并且不涉及析构函数。

编辑:看来您可能担心资源泄漏。由于 Test 没有管理任何资源,因此不会有泄漏,编译器生成的成员将表现良好。如果您的类确实管理资源(通常以动态分配内存的形式),那么您将需要应用 rule of 3/5/0 .值得注意的是,您将需要自己实现赋值运算符,以便它清理所有以前持有的资源。仅实现析构函数是不够的,因为它不参与赋值。

关于C++ 析构函数调用了错误的对象?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54223415/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com