首页 > 解决方案 > 按值传递类时,调用者或被调用者是否调用析构函数?

问题描述

假设我有以下(精简)代码:

class P { P(); P(const P&); ~P(); }

void foo(P x) {
  ...
}

void bar() {
  P p{};
  foo(p); // compiler uses P::(const P&) to construct the value for x
  ...
  // compiler calls P::~P() on p
}

编译器必须创建一个副本p才能调用foo,因此调用者在调用之前调用复制构造函数。我的问题是,谁负责销毁这个创建的对象?似乎有两个有效的选择:

  1. 被调用者(即foo)在它返回之前调用其所有按值参数的析构函数,然后调用者释放内存(通过将其从堆栈中弹出)。
  2. 被调用者不做任何事情,调用者(即bar)在调用结束时的序列点之前的所有临时对象上调用析构函数foo(p)

标签: c++language-lawyerdestructor

解决方案


该标准在 [expr.call]/4 中回答了这个问题,其详细程度令人惊讶:

...每个参数的初始化和销毁​​发生在调用函数的上下文中。[示例:在调用函数的调用点检查构造函数、转换函数或析构函数的访问。如果函数参数的构造函数或析构函数抛出异常,则在调用函数的范围内开始搜索处理程序;特别是,如果被调用的函数有一个function-try-block(第 18 条)和一个可以处理异常的处理程序,则不考虑这个处理程序。—结束示例]

换句话说,析构函数由调用函数调用。


推荐阅读