函数调用中的 C++ 临时对象生命周期

C++ temporary objects lifetime in a function call

当我们通过原始指针或引用将临时智能指针管理的对象传递给函数时,标准是否保证对象的生命周期会延长到函数的生命周期?

#include <iostream>
#include <memory>

struct A {
  ~A() {
    std::cout << "~A()" << std::endl;
  }
};

std::unique_ptr<A> makeA() {
  return std::make_unique<A>();
}

void f(const A& a) {
  std::cout << "f()" << std::endl;
}

int main() {
  f(*makeA());
  return 0;
}

我希望 unique_ptr 管理的 A 的实例一旦从中获得原始指针就会被销毁,因为它是一个临时指针并且没有绑定到函数参数。所以输出可能是

~A()
f()

但是 gcc 和 clang 都让它一直运行到函数结束,即输出是

f()
~A()

看来临时智能指针并没有被破坏

为什么 A 实例(位于堆中)一直存活到函数结束?非常感谢对该标准的一些参考。

临时对象一直存在到创建它们的完整表达式结束(有一些生命周期延长例外),请参阅[class.temporary]/4

在你的例子中,std::unique_ptr<A> 类型的临时对象是由 makeA() 创建的,而这是其子表达式的完整表达式是 f(*makeA());,因此临时对象的生命周期将以该分号结束。

unique_ptr管理的对象也只有在unique_ptr本身被销毁时才被销毁(这就是智能指针的目的)。

有关该规则的例外情况,请参阅标准的以下段落。

*makeA() 正在取消引用由调用 makeA.

创建的 匿名临时文件

标准保证匿名临时函数在函数调用后仍然存在 - 换句话说,~A 在程序控制到达语句末尾时在概念上被调用。

根据标准,[class.temporary]/4

(强调我的)

Temporary objects are destroyed as the last step in evaluating the full-expression ([intro.execution]) that (lexically) contains the point where they were created. This is true even if that evaluation ends in throwing an exception. The value computations and side effects of destroying a temporary object are associated only with the full-expression, not with any specific subexpression.

也就是说,它与绑定到函数参数的临时无关,由makeA()构造的临时不会被销毁,直到完整表达式结束,其中包括调用函数 f.