11

我有一个对象,里面有一些指针。析构函数调用delete这些指针。但有时我想删除它们,有时我不想。所以我希望能够在调用析构函数的情况下删除对象。这可能吗?

编辑:我意识到这是一个可怕的想法,没有人应该这样做。尽管如此,我还是想这样做,因为它会使一些内部函数更容易编写。

4

7 回答 7

12

运算符对delete传递给它的对象做了两件事:

  • 调用适当的析构函数。
  • 调用释放函数,operator delete.

因此,在不调用析构函数的情况下删除对象意味着您只想调用operator delete该对象:

Foo *f = new Foo;
operator delete(f);

operator delete是一个普通的函数调用,并且完成了通常的名称查找和重载解析。但是,delete操作员有自己的规则来查找正确的operator delete. 例如,运算符将查找通常名称查找和重载解析找不到delete的成员函数。operator delete这意味着您需要确保在手动使用operator delete.

正如您所说,operator delete直接使用是一个糟糕的主意。未能调用析构函数会破坏 RAII,从而导致资源泄漏。它甚至可能导致未定义的行为。此外,您必须承担编写没有 RAII 的异常安全代码的责任,这非常困难。你几乎肯定会弄错。

于 2013-02-14T19:03:46.557 回答
7

您可以将指针设置为 NULL,然后析构函数不会删除它们。

struct WithPointers
{
    int* ptr1;
    int* ptr2;

    WithPointers(): ptr1(NULL), ptr2(NULL) {}

    ~WithPointers()
    {
        delete ptr1;
        delete ptr2;
    }
}

...
WithPointers* object1 = new WithPointers;
WithPointers* object2 = new WithPointers;
object1->ptr1 = new int(11);
object1->ptr2 = new int(12);
object2->ptr1 = new int(999);
object2->ptr2 = new int(22);
...
int* pointer_to_999 = object2->ptr1;
object2->ptr1 = NULL;
delete object1;
delete object2; // the number 999 is not deleted now!
// Work with the number 999
delete pointer_to_999; // please remember to delete it at the end!
于 2013-02-14T18:12:10.207 回答
4

哇!是的,有可能,不,我不会这样做。让需要变量生命周期的对象通过共享指针或其他一些引用计数对象来控制。使用 C++ 比破坏它的一些内部租户更干净......

于 2013-02-14T18:05:39.320 回答
2

是的,这是可能的。 std::vector这样做是因为它为对象分配了带有空间的缓冲区,然后有条件地(就地)构造它们并销毁它们,独立于对象生命周期管理内存。

在 C++11 中,我将使用union您的类型和带有微不足道的构造函数/析构函数的小型类型来指示可以适合您的类型的内存位置,但不必在其中包含该类型。除此之外,您必须跟踪对象是否确实存在。创建项目包括使用放置new,销毁它包括手动调用析构函数。

对象的缓冲区union,无论是 N 个对象还是 1 个,都将完全独立管理。的默认构造函数union要么不构造任何东西,要么构造普通类型(在这种情况下,您可能想要销毁该普通类型)。

但是,您的问题的真正答案很可能是“不要那样做”。如果你这样做,你把指针包装在一个唯一class的工作就是处理上面的混乱中。这种类型的类(其工作是管理指针的生命周期和类似指针的属性)称为“智能指针”。

于 2013-02-14T18:15:39.457 回答
2

无论您实际尝试做什么,您的代码都存在问题。如果您不想删除子对象,只需使用在删除对象之前设置的布尔标志,析构函数将考虑该标志。

但老实说,您应该使用智能指针而不是裸指针(在您的情况下,看起来共享指针就是您所需要的)。

于 2013-02-14T18:08:19.543 回答
2

编写一个可以在调用析构函数之前调用的方法。该方法将翻转成员布尔值。当析构函数被调用时,它将检查该布尔成员,如果为真则销毁指针,如果为假则保留它。

我不建议这样做。最好让类不负责删除指针。

于 2013-02-14T18:13:10.297 回答
1

正如其他人所建议的那样,解决此问题的正确方法不是不调用析构函数[您只需要向对象添加类似std::stringstd::vector的内容,然后突然之间就会出现内存泄漏]。正确的方法是要么根本不让你的对象拥有那些其他对象(例如在对象被删除之前/之后分别删除它们),要么有一个方法让对象知道是否删除指针。

于 2013-02-14T18:11:59.957 回答