因此,我是一个初学者,试图掌握操作符new。我的析构函数怎么了?
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()之后。
谢谢!
发布于 2011-01-19 23:57:24
乍一看,你不应该显式地调用析构函数。相反,使用作用域强制超出作用域并调用析构函数。
int main()
{
{
arr a;
} //This calls destructor of a
//Rest of code
}
否则,a的析构函数会被调用两次:一次是在调用它时,另一次是在a超出作用域时。
编辑:
给你。
http://www.parashift.com/c++-faq-lite/dtors.html
发布于 2011-01-19 23:56:04
问题是您显式地调用了a
上的析构函数(a.~arr()
),而当a
在main()
结束时超出作用域时,析构函数已经被自动调用了。第二次调用析构函数时,将对已析构的对象调用。从技术上讲,这导致了未定义的行为(这是一种方式,即根据C++标准,任何结果都是可以接受的)。在实践中,此代码很可能只是再次执行析构函数,将存储在内存位置中的地址传递给::operator delete()
(可能是也可能不是构造函数存储在那里的地址),该地址由调试运行时捕获。
如果你想在main()
中间删除a
,你应该做的是引入一个额外的作用域:
int main()
{
{
arr a;
} //a will be deleted here
// rest of main
}
另一种方法是不使用自动对象,而是使用动态对象,您可以为其设置生命周期。
但是你的代码还有另一个问题,你没有问过这个问题,但我仍然觉得有必要指出:
您的类迫切需要一个复制构造函数和一个赋值操作符。(至少,将它们声明为private
,以便禁止复制。)根据Rule Of Three,你需要一个析构函数的事实应该会给你一个提示,其他两个也是需要的。
您可以通过不尝试手动管理动态分配的内存来避免所有麻烦。取而代之的是使用一个为你做这件事的类型:
class arr{
public:
arr() : pool(100*sizeof(double)) {
}
// ~arr() // not needed any longer
std::vector<char> pool;
};
发布于 2011-01-19 23:58:42
你不需要为堆栈上创建的对象调用析构函数。变量'a‘在堆栈上,超出作用域时将自动删除。
https://stackoverflow.com/questions/4737403
复制相似问题