C++ 显式调用析构函数

C++ 显式调用析构函数,c++,destructor,C++,Destructor,我理解在大多数情况下,我们不应该显式地调用析构函数。但是,我看到了C++11标准N3485第13.4.5节模板参数中的一个示例: 对具有以下类型的对象的显式析构函数调用 是一个类模板专门化可以显式指定 模板参数。例如: template<class T> struct A { ~A(); }; void f(A<int>* p, A<int>* q) { p->A<int>::~A(); // OK: destr

我理解在大多数情况下,我们不应该显式地调用析构函数。但是,我看到了C++11标准N3485第13.4.5节模板参数中的一个示例:

对具有以下类型的对象的显式析构函数调用 是一个类模板专门化可以显式指定 模板参数。例如:

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
}
模板结构A{
~A();
}; 
空f(A*p,A*q){
p->A::~A();//确定:析构函数调用
q->A::~A();//确定:析构函数调用
}
在我看来,在这种情况下我们可以显式地调用析构函数,你能解释一下为什么吗?在这个例子中,那些析构函数调用意味着什么?为什么它们是合理的

另一个问题:

除了在实现
placement delete
时,还可以显式调用析构函数的情况有哪些?

多谢各位

EDIT:我从中发现,我们不应该显式调用局部变量的析构函数

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

你是说为什么我们可以?因为该语言允许对任何对象进行显式析构函数调用。正如您所说,它通常会给出未定义的行为,因为大多数对象都会以其他方式被销毁,而两次销毁任何对象(或者更一般地说,在销毁后访问它)都是未定义的行为。但这只是意味着你不能这么做,而不是语言会阻止你这么做

或者你是说我们为什么要这么做?因为这就是你如何破坏一个由新放置创建的对象

在这个例子中,那些析构函数调用意味着什么

它们的意思是一样的,相当于
p->~A()
;它们调用对象的析构函数。该示例演示了如果需要,可以在此处提供模板参数。我不知道你为什么要这么做

除了placement delete之外,我们还可以显式调用析构函数的情况有哪些


我认为你可以随时调用一个微不足道的析构函数(一个什么都不做的函数);但是没有意义。我认为销毁用placement new创建的东西是唯一合法的理由。

在这种情况下,我觉得我们可以显式地调用析构函数,你能解释一下原因吗?

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

在本例中,这些析构函数调用意味着什么?

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

为什么它们是合理的?

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

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

除了placement delete之外,我们还可以显式调用析构函数的情况有哪些?

除了placement new对应的运算符之外,实际上没有“placement delete”这样的东西(对
delete
的任何调用都将隐式调用析构函数,除了编译器为构造失败而调用的那些,例如“placement delete”概念)

上面我举了一个例子。另一个例子是
std::vector
。您可以调用成员函数,如
pop\u back()
。这需要销毁向量中的最后一个元素,但它不能使用
delete
,因为支持对象的内存是必须单独管理的较大缓冲区的一部分。许多其他容器也是如此,如开放寻址哈希表、
deque
,等等。这是您希望使用
模板typename
显式调用析构函数的示例


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

参考文章是关于显式调用局部变量的析构函数,其析构函数也在其作用域的末尾被隐式调用。+1我在代码中做了一些类似的废话,显式调用析构函数来销毁我的对象(或者至少它似乎可以工作)。但我在托管类型上做过。去看电影会很有趣的answers@AndyThomas-我明白,我的意思是引用显式析构函数调用标准的答案的解释。我的帖子有误导性吗?如果这是一个问题,我将尝试重写它。@taocp-只是在这里澄清一下,就像在引用的文章中一样,未定义的行为并没有显式调用析构函数-它导致它在同一对象上被多次调用。@AndyThomas Cramer啊,我同意。我主要看答案。我会尽力改正的。非常感谢。对于分配了存储空间的对象也是这样吗?我曾经在Win form上这样做过一次,我显式调用析构函数来销毁form对象,但是如果它是UB,那么我知道我现在必须更改代码。+1。此外,关于琐碎的析构函数,您是正确的,因为§3.8/1定义了