明确地调用析构函数

tao*_*ocp 44 c++ destructor

我知道在大多数情况下,我们不应该明确地调用析构函数.但是,我在C++ 11 Standard N3485第13.4.5节模板参数中看到了一个例子:

对具有类模板特化的类型的对象的显式析构函数调用可以显式指定template-arguments.例:

template<class T> struct A {
    ~A();
}; 

void f(A<int>* p, A<int>* q) {
    p->A<int>::~A();      // OK: destructor call
    q->A<int>::~A<int>(); // OK: destructor call
}
Run Code Online (Sandbox Code Playgroud)

在我看来,在这种情况下我们可以明确地调用析构函数,你能解释一下为什么吗?在这个例子中,这些析构函数的含义是什么意思?为什么他们合理?

另一个问题:

除了我们实现之外,我们可以明确地调用析构函数的情况是什么placement delete

谢谢.

编辑:我从C++ FAQ中发现,我们不应该在局部变量上显式调用析构函数.

Mik*_*our 31

在我看来,在这种情况下我们可以明确地调用析构函数,你能解释一下为什么吗?

你的意思是我们为什么可以?因为该语言允许对任何对象进行显式析构函数调用.正如你所说的,它通常会给出未定义的行为,因为大多数对象都会以其他方式被破坏,并且它是未定义的行为来销毁任何东西两次(或者更常见的是在破坏之后访问它).但这只是意味着你不能这样做,而不是语言会妨碍你这样做.

或者你的意思是我们为什么要这样做?因为这就是你如何破坏由贴牌新创建的对象.

在这个例子中,这些析构函数的含义是什么意思?

它们都意味着相同的东西,相当于p->~A(); 他们称对象为析构函数.该示例演示如果您愿意,可以在此处提供模板参数.我不确定你为什么要这样做.

除了放置删除之外,我们可以明确调用析构函数的情况是什么?

你可以随时打电话给一个简单的析构函数(一个什么都不做); 但没有意义.我认为破坏使用placement new创建的东西是唯一合理的理由.


Sea*_*tch 25

在我看来,在这种情况下我们可以明确地调用析构函数,你能解释一下为什么吗?

因为语言允许随时调用任何对象的析构函数(假设您有访问权限,例如它不是私有析构函数).

在这个例子中,这些析构函数的含义是什么意思?

它只是调用析构函数.从逻辑上讲,这意味着该对象被破坏,应该被认为是该点上的垃圾,不应该被解除引用或使用.从技术上讲,它意味着对象处于析构函数离开它的任何状态,对于某些对象可能与默认构造相同(但您永远不应该依赖于此).

为什么他们合理?

有时您需要在不释放内存的情况下销毁对象.这种情况发生在很多类中,例如variant/any,各种脚本绑定和反射系统,一些单例实现等.

例如,您可以使用std::aligned_storage为对象分配缓冲区,然后使用placement new在该缓冲区中构造对象.你不能调用delete这个对象,因为它会调用析构函数并尝试释放支持它的内存.在这种情况下,您必须显式调用析构函数才能正确地销毁对象.

除了放置删除之外,我们可以明确调用析构函数的情况是什么?

除了相应的操作符放置new之外,并没有真正的'placement delete'这样的东西(并且任何调用都delete将隐式调用析构函数,除非编译器调用失败的构造,例如你的'placement delete'概念).

我上面给出的一个例子.另一个例子是std::vector.你可以调用成员函数pop_back().这需要销毁向量中的最后一个元素,但它无法使用,delete因为支持该对象的内存是必须单独管理的较大缓冲区的一部分.许多其他容器也是如此,例如开放寻址哈希表,deque等等.这是您要使用的示例,template typename以便显式调用析构函数.

这是一个库的用户很少需要的功能,但像STL这样的低级库的实现者甚至某些应用程序框架都需要在这里和那里使用.