手动调用析构函数总是设计不良的标志吗?

102

我在思考:人们说如果你手动调用析构函数,那么你正在做一些错误的事情。但这总是正确的吗?是否存在任何反例?有没有必要手动调用析构函数的情况,或者避免手动调用析构函数很难/不可能/不切实际的情况?


在调用析构函数后,你如何释放对象而不再次调用它? - ssube
2
@peachykeen:你可以调用放置new来用新对象替换旧对象进行初始化。通常不是一个好主意,但也不是没有先例。 - D.Shawley
18
查看那些包含“总是”和“从不”这些词汇的“规则”,而这些规则并非直接来自规范。这些规则值得怀疑:在大多数情况下,教授这些规则的人想要隐藏你应该知道的东西,但他不知道如何教授。就像成年人回答孩子有关性的问题一样。 - Emilio Garavaglia
我认为在使用放置技术构造对象时,这是可以接受的(但这是相对较低级别的事情,只有在优化软件时才会使用,即使在这种程度上)。http://www.stroustrup.com/bs_faq2.html#placement-delete - Konstantin Burlachenko
12个回答

0

我从未遇到过需要手动调用析构函数的情况。我似乎记得甚至 Stroustrup 也认为这是一种不好的做法。


1
你说得对。但我使用了一个放置new。我能够在除了析构函数之外的方法中添加清理功能。析构函数存在是为了在执行delete时可以“自动”调用它,当您手动想要析构但不想释放内存时,您可以简单地编写一个“onDestruct”,您有没有兴趣听听是否有对象必须在析构函数中进行销毁的示例,因为有时您需要删除,而其他时候您只想析构而不想释放内存。 - Lieuwe
即使在那种情况下,您也可以从析构函数内调用onDestruct() - 所以我仍然不认为手动调用析构函数有必要。 - Lieuwe
5
@JimBalter: C+ 的创造者 ☺ - Mark K Cowan
@MarkKCowan:C+是什么?应该是C++。 - Destructor

-4

我有另一种情况,我认为调用析构函数是完全合理的。

当编写“重置”类型的方法以将对象恢复到其初始状态时,调用析构函数以删除正在重新设置的旧数据是完全合理的。

class Widget
{
private: 
    char* pDataText { NULL  }; 
    int   idNumber  { 0     };

public:
    void Setup() { pDataText = new char[100]; }
    ~Widget()    { delete pDataText;          }

    void Reset()
    {
        Widget blankWidget;
        this->~Widget();     // Manually delete the current object using the dtor
        *this = blankObject; // Copy a blank object to the this-object.
    }
};

2
如果在这种情况下声明一个特殊的cleanup()方法来调用析构函数,会不会看起来更清晰? - Violet Giraffe
一个“特殊”的方法只在两种情况下被调用?当然...听起来完全正确(/讽刺)。方法应该是通用的,可以在任何地方调用。当你想删除一个对象时,调用它的析构函数没有任何问题。 - abelenky
5
在这种情况下,您不能显式调用析构函数。无论如何,您都必须实现一个赋值运算符。 - Rémi

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接