何时需要进行显式析构函数调用?

3

是否存在一些情况,使用标准的new/delete不足以满足我们的需求,需要显式调用析构函数,例如pA->~A()

我认为这只在一些资源管理类中是必要的,但通常不是一个好主意。析构函数会在作用域结束时自动调用,所以为什么要手动调用呢?

通过示例进行解释会更好!

2个回答

7
在C++11中,您可以使用需要析构函数的类型创建一个联合(union)。由于编译器无法跟踪当前活动的成员是哪个类型,因此当替换当前活动成员或销毁联合时,您需要显式地销毁当前成员。标准在 9.5 [class.union] 第4段中使用以下示例代码,将当前活动成员 m 切换为新活动成员 n
u.m.~M();
new (&u.n) N;

+1 TIL,至少在C++11中,您可以放置“new”(并手动销毁)“union”成员。我似乎记得这在C++03中是UB(未定义行为),尤其是在使用非POD类型的“union”时。 - C. K. Young
@ChrisJester-Young:我认为在C++03中这不是未定义行为:我认为在C++03中,当尝试将非POD作为union的成员使用时,编译器需要创建一条诊断信息。 - Dietmar Kühl

6
另一个显式调用析构函数的情况是手动使用放置new构造的对象。
假设您正在尝试使用malloc/free兼容的API(例如,与允许指定自定义C样式分配器的C客户端进行交互),请看下面的例子:
void* buf = malloc(sizeof (MyType));
if (buf) {
    MyType* foo = new (buf) MyType;
    // ...
    foo->~MyType();
    free(buf);
}

(尽管在这种情况下,最好使用带有自定义删除器的shared_ptrunique_ptr。)

你是指调用 delete 吗?能否举个例子? - Oleksiy
@Oleksiy 你只能使用delete释放通过new分配的对象。我提供了一个例子,其中底层内存是使用malloc分配的。 - C. K. Young
1
@计算机 不,delete并不 (必然) 使用 free,就像 new 不(必然)使用 malloc 一样。C++系统有其自己的分配器,默认的 newdelete 使用它。无论如何,这都是无关紧要的,因为我的例子应该是可推广到 C 客户端指定自定义分配器(使用 malloc/free 接口)的情况。 - C. K. Young
1
@computer 当你使用malloc函数分配内存后,便不能再用delete来释放此内存。这是因为malloc分配内存可能与new分配的不同。虽然new可以在幕后使用malloc,但使用时需谨慎。参见:https://dev59.com/f3VC5IYBdhLWcg3wnCaA#240308 - C. K. Young
我知道这个,但在这里我可以看到foo是用new创建的,对吗?是的,事实上这是放置new,这就是为什么我不能删除foo的原因。 - 4pie0
显示剩余3条评论

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