所以我是一个初学者试图掌握操作员新手。我的析构函数有什么问题?
class arr{
public:
arr(){
pool=::operator new(100*sizeof(double));
}
~arr(){
::operator delete(pool);
}
void* pool;
};
int main()
{
arr a;
a.~arr(); //If I comment this out it's ok.
void* pool2=::operator new(100*sizeof(double)); //Works
::operator delete(pool2); //Fine.
system("pause");
return 0;
}
离开.~arr();在给我这个错误:
调试断言失败了!文件:dbgdel.cpp行:52
表达式:_BLOCK_TYPE_IS_VALID(pHead-> nBlockUse)
我无法理解为什么pool2工作正常但是使用该类会给我带来麻烦。系统“暂停”之后只会弹出错误,这是在.~arr()被调用之后???
谢谢!
答案 0 :(得分:7)
嗯,乍一看,你不应该明确地调用析构函数。而是使用作用域强制超出范围并调用析构函数。
int main()
{
{
arr a;
} //This calls destructor of a
//Rest of code
}
否则a的析构函数会被调用两次:一次调用它时,一次调用超出范围时。
编辑:
你好。
答案 1 :(得分:6)
问题是您在a
(a.~arr()
)上显式调用了析构函数,而 析构函数将在{时自动调用 {1}}在a
结尾处超出范围。当第二次调用析构函数时,在已经被破坏的对象上调用 。从技术上讲,这会导致 未定义行为 (根据C ++标准,这可以说任何结果都没问题)。实际上,这段代码可能只是再次执行析构函数,将存储在以前为main()
的内存位置的地址传递给a.pool
(可能是也可能不是构造函数存储在那里),它由Debug运行时捕获。
如果您希望在::operator delete()
的中间删除a
,则应该做的是引入其他范围:
main()
另一种方法是不使用自动对象,而是使用动态对象,您可以为其设置生命周期。
但是你的代码还有 另一个问题 ,你没有问过,但我觉得有必要指出:
您的班级迫切需要 复制构造函数 和 赋值运算符 。 (至少,声明它们int main()
{
{
arr a;
} //a will be deleted here
// rest of main
}
以禁止复制。)根据Rule Of Three,你需要一个析构函数的事实应该给你一个暗示,其他两个也是必需的。
您可以通过不尝试手动管理动态分配的内存来避免所有麻烦。而是使用为您执行此操作的类型:
private
答案 2 :(得分:0)
您不需要为堆栈上创建的对象调用析构函数。变量'a'在堆栈上,当超出范围时将自动删除。