运营商新/删除&析构函数

时间:2011-01-19 15:54:00

标签: c++ visual-c++ memory-management destructor

所以我是一个初学者试图掌握操作员新手。我的析构函数有什么问题?

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()被调用之后???

谢谢!

3 个答案:

答案 0 :(得分:7)

嗯,乍一看,你不应该明确地调用析构函数。而是使用作用域强制超出范围并调用析构函数。

int main()
{
    {
        arr a;
    } //This calls destructor of a

    //Rest of code
}

否则a的析构函数会被调用两次:一次调用它时,一次调用超出范围时。

编辑:

你好。

http://www.parashift.com/c++-faq-lite/dtors.html

答案 1 :(得分:6)

问题是您在aa.~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'在堆栈上,当超出范围时将自动删除。