运算符新建/删除&析构函数

发布于 2024-10-13 06:38:50 字数 646 浏览 6 评论 0原文

所以我是一个初学者,试图掌握operator 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;
}

留下a.~arr();给我这个错误:

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

表达式:_BLOCK_TYPE_IS_VALID(pHead->nBlockUse)

我不明白为什么 pool2 工作正常但使用该类给我带来了问题。此外,该错误仅在系统“暂停”后才会弹出,即在调用 a.~arr() 之后???

谢谢!

So I'm a beginner trying to get to grips with operator new. What's wrong with my 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;
}

Leaving a.~arr(); in gives me this error:

Debug assertion failed! File: dbgdel.cpp line: 52

Expression: _BLOCK_TYPE_IS_VALID(pHead->nBlockUse)

I can't see why pool2 works fine but using the class gives me problems. Also the error only pops up after the system "pauses", which is after a.~arr() is called???

Thanks!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

懒猫 2024-10-20 06:38:50

嗯,乍一看,您不应该显式调用析构函数。相反,使用作用域来强制超出范围并调用析构函数。

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

    //Rest of code
}

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

编辑:

给你。

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

Well, at a glance, you should not be explicitly calling the destructor. Instead use scoping to force a out of scope and call the destructor.

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

    //Rest of code
}

Otherwise the destructor of a gets called twice: once when you call it and again when a goes out of scope.

EDIT:

Here ya go.

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

想挽留 2024-10-20 06:38:50

问题是您在 a (a.~arr()) 上显式调用析构函数,而析构函数已经被自动调用amain() 末尾超出范围时。当第二次调用析构函数时,在已析构的对象上调用。从技术上讲,这会导致未定义行为(这是一种表示根据 C++ 标准任何结果都很好的方式)。实际上,这段代码可能只是再次执行析构函数,将存储在曾经是 a.pool 的内存位置中的地址传递给 ::operator delete() (这可能是也可能不是构造函数存储在那里的内容),由调试运行时捕获。

如果您希望在 main() 中间删除 a,您应该做的是引入一个额外的作用域:

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

  // rest of main

}

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


但是您的代码还有另一个问题,您没有询问,但我仍然觉得有必要指出:

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

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

    }
    // ~arr() // not needed any longer
    std::vector<char> pool;
};

The problem is that you explicitly invoke the destructor on a (a.~arr()), while the destructor will already be invoked automatically when a goes out of scope at the end of main(). When the destructor is called for the second time, it is called on an already destructed object. Technically, this leads to Undefined Behavior (which is a way to say that any result will be fine according to the C++ standard). In practice this code will likely just execute the destructor again, passing the address stored in the memory location that used to be a.pool to the ::operator delete() (which might or might not be what the constructor stored there), which is caught by the Debug runtime.

What you should do instead if you want a to be deleted in the middle of main() is to introduce an additional scope:

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

  // rest of main

}

Another way would be to not to use an automatic object, but a dynamic one, for which you can set a lifetime.


But there's another problem with your code, which you didn't ask about, but which I nevertheless feel a need to point out:

Your class urgently needs a copy constructor and a assignment operator. (At the very least, declare them private in order to disallow copying.) As per the Rule Of Three, the fact that you need a destructor should give you a hint that the other two are needed as well.
You can avoid all the hassle by not attempting to manually manage dynamically allocated memory. Instead use a type which does this for you:

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

    }
    // ~arr() // not needed any longer
    std::vector<char> pool;
};
无风消散 2024-10-20 06:38:50

您不需要为堆栈上创建的对象调用析构函数。变量“a”位于堆栈中,超出范围时将自动删除。

you don't need to call destructor for objects created on stack. The variable 'a' is on stack and will be deleted automatically when out of scope.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文