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

Mik*_*ail 2 c++ expression lifetime

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

#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;
}
Run Code Online (Sandbox Code Playgroud)

我希望一旦从A管理器实例unique_ptr获取到原始指针后,该实例将被销毁,因为它是临时的,并且未绑定到函数参数。所以输出可能是

~A()
f()
Run Code Online (Sandbox Code Playgroud)

但是gcc和clang都使它生效,直到函数结束,即输出为

f()
~A()
Run Code Online (Sandbox Code Playgroud)

因此,似乎临时智能指针没有被破坏。

为什么A实例(位于堆中)一直存活到函数结束?高度赞赏对该标准的一些参考。

wal*_*nut 6

临时对象会一直生存到创建它们的完整表达式的末尾(某些生命周期延长例外)。在您的情况下,type感兴趣的临时对象std::unique_ptr<A>是由创建的makeA(),而full表达式是is的子表达式f(*makeA());,因此,该临时对象的生存期将以该分号结束。

unique_ptr仅当销毁管理对象时unique_ptr(它本身就是智能指针的目的),销毁的对象也会被销毁。

标准(草稿)参考(与较早的C ++版本相同):

[class.temporary] / 4

[...]临时对象被销毁,是评估(按词法)包含创建点的完整表达式([intro.execution])的最后一步。[...]

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


son*_*yao 5

从标准来看,[class.temporary]/4

(强调我的)

临时对象在计算完整表达式 ( [intro.execution] ) 的最后一步被销毁,该表达式(词法上)包含它们的创建点。即使该评估最终引发异常也是如此。销毁临时对象的值计算和副作用仅与完整表达式相关联,而不与任何特定的子表达式相关联。

这意味着,它与绑定到函数参数的临时变量无关,makeA()在完整表达式结束(包括 function 的调用)之前, 构造的临时变量不会被销毁f