5

我意识到这是不明智的,我不打算这样做,但我很好奇以下内容是否实际上是非法的:

#include <iostream>

struct X
{
    ~X()
    {
        std::cout << "~X()\n";
    }
};

int main()
{
    X *x = new X;
    //delete x;
    x->~X();
    ::operator delete(x);
    return 0;
}

我的理解delete x;是相当于调用析构函数然后调用::operator delete(x);,但是我按照标准手动这样做合法吗?我知道在使用新位置时这是一个有效的事情,但是在非位置的情况下呢?我的预感是它可能是非法的,因为delete(而不是operator delete)必须为 each 执行new,但我很想知道。

4

5 回答 5

3

我很确定这不符合标准。在标准中(我知道)中没有任何地方说操作数delete p;直接传递给释放函数,并且delete []几乎可以肯定它不会原封不动地传递。

但是,它可能适用于所有实际实现。

当然,您不应该显式调用全局释放函数。在您的示例中很好,它没有用户定义的分配和释放函数,但在一般情况下没有(实际上,是否有任何语法用于调用特定于类的释放函数(如果存在),否则调用全局函数? )。

另外,一般情况下,传递给释放函数的指针绝对不是delete的操作数。考虑:

struct A
{
  virtual ~A() {}
};

struct B1 : virtual A {};

struct B2 : virtual A {};

struct B3 : virtual A {};

struct D : virtual B1, virtual B2, virtual B3 {};

struct E : virtual B1, virtual D {};

int main( void )
{
  B3* p = new D();
  p->~B3(); // should be ok, calling virtually
  operator delete(p); // definitely NOT OK

  return 0;
}
于 2010-12-12T20:42:22.723 回答
3

如果你要这样,你应该更换

X *x = new X;

经过

X* x = static_cast<X*>(::operator new(sizeof(X)));

try { new(x) X; }
catch (...) { ::operator delete(x); throw; }

这应该(如果我错了,请纠正我)与您的销毁方法一致,并且在功能上与new.

于 2011-02-09T16:44:59.957 回答
2

我相信如果你调用析构函数并释放内存,你就不会调用未定义的行为。

于 2010-12-12T15:18:07.777 回答
1

@StuartGolodetz

Answer, and reply to a comment

There may well be some template metaprogramming one can do to make sure the global one is called otherwise, but I'm not an expert on that. It's probably an SFINAE thing of some sort if it is possible I'd guess.

struct B {
    virtual ~B();
};

struct D : B {
    operator new (size_t);
    operator delete (void*);
};

B *p = new D;

decltype(typeid(*p))::operator delete (...); // hypothetical C++++

Meta this!

于 2011-11-01T05:02:52.647 回答
0

我以为

::operator delete(x);

是相同的

delete x;

如果该delete方法没有被 X 覆盖?

于 2010-12-12T20:28:52.970 回答