运算符new/delete&destructors

Jac*_*ack 1 c++ destructor memory-management visual-c++

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

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;
}
Run Code Online (Sandbox Code Playgroud)

离开.~arr(); 在给我这个错误:

调试断言失败了!文件:dbgdel.cpp行:52

表达式:_BLOCK_TYPE_IS_VALID(pHead-> nBlockUse)

我不明白为什么pool2工作正常,但使用该类给我带来了问题.系统"暂停"后也会弹出错误,这是在.~arr()被调用之后???

谢谢!

Jam*_*mes 7

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

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

    //Rest of code
}
Run Code Online (Sandbox Code Playgroud)

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

编辑:

你去吧.

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


sbi*_*sbi 6

问题是您在a(a.~arr())上显式调用析构函数,而在结束时超出范围时,析构函数将自动被调用.当第二次调用析构函数时,会在已经被破坏的对象上调用它.从技术上讲,这会导致未定义的行为(根据C++标准,这可以说任何结果都可以.)在实践中,这段代码可能只是再次执行析构函数,将存储在以前存储器位置的地址传递给(运行时可能存在或者可能不存在构造函数),这是由Debug运行时捕获的.amain()a.pool::operator delete()

如果你想a在中间删除,你应该做的main()是引入一个额外的范围:

int main()
{
  {
    arr a;
  } //a will be deleted here

  // rest of main

}
Run Code Online (Sandbox Code Playgroud)

另一种方法是不使用自动对象,而是使用动态对象,您可以为其设置生命周期.


但是你的代码存在另一个问题,你没有问过,但我觉得有必要指出:

您的班级迫切需要一个复制构造函数赋值运算符.(至少,声明它们private是为了禁止复制.)根据规则三,你需要一个析构函数的事实应该给你一个暗示,其他两个也是需要的.
您可以通过不尝试手动管理动态分配的内存来避免所有麻烦.而是使用为您执行此操作的类型:

class arr{
public:
    arr() : pool(100*sizeof(double)) {

    }
    // ~arr() // not needed any longer
    std::vector<char> pool;
};
Run Code Online (Sandbox Code Playgroud)