Bob*_*yan 0 c++ destructor visual-c++
我在具有最新更新的 Visual Studio 2022 社区版中使用 Visual C++。在下面的 C++ 代码中,main 创建了 ShowBug 的实例并将其分配给变量 sb。下一行创建 ShowBug 的第二个实例并将其分配给 sb。
在第二行完成之前,它调用析构函数。但是,它不会破坏第一个实例,这正是我认为它会做的,而是破坏了新创建的第二个实例。如果您觉得难以置信,请亲自尝试一下。
那么,我是否在这里遗漏了一些东西(即使用相同的变量来分配新实例是一种糟糕的编程习惯?),或者编译器是否以某种方式做了正确的事情?或者,这是一个编译器错误吗?
// ShowBug.h:
using namespace std;
#include <iostream>
#include <string>
class ShowBug
{
// This class is used to show that the destructor seems to be called for the wrong instance.
//
string S;
int *pArray;
public:
inline ShowBug(const string &s) : S(s)
{
}
inline ~ShowBug()
{
std::cout << "Deleting " + S;
}
};
int main()
{
ShowBug sb = ShowBug("First Instance");
sb = ShowBug("Second Instance");
}
Run Code Online (Sandbox Code Playgroud)
当你这样做时
sb = ShowBug("Second Instance");
Run Code Online (Sandbox Code Playgroud)
该表达式ShowBug("Second Instance")创建类型为 的临时ShowBug对象。一旦完整的表达式(赋值)完成,这个临时对象将立即被销毁。
这当然会导致问题,因为它的销毁也会释放分配的内存。指针将被赋值复制,但只是指针本身,而不是它指向的内存。
所以赋值后指针sb.pArray将不再有效。除了使用错误的delete运算符之外,再次尝试delete无效指针也会导致未定义的行为。
解决方案是遵循三、五或零规则之一。我建议使用零规则,std::vector<int>在您的情况下使用 orstd::array<int, 3>而不是您现在所做的动态分配。然后你可以删除析构函数。
如果必须使用指针和动态分配,那么您需要至少遵循三规则,并实现复制构造函数和复制赋值运算符。
我还忽略了初始化
ShowBug sb = ShowBug("First Instance");
Run Code Online (Sandbox Code Playgroud)
有完全相同的问题:您创建一个临时对象,用于复制构造该sb对象。然后临时对象被销毁,并带走内存和原始指针。
但解决方案仍然是一样的:零、三或五的规则。
| 归档时间: |
|
| 查看次数: |
79 次 |
| 最近记录: |