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

Lifetime of temporaries inside a function call

请看下面的代码示例:

(一)

#include <iostream>
#include <utility>
struct wrapper {
  int&& x;
};

void f(wrapper a) { std::cout << std::move(a.x) << std::endl; }
int g() { return 0; }

int main() {
  f(wrapper{g()});
}

(B)

#include <iostream>
#include <utility>
struct wrapper {
  int&& x;
};
wrapper make_wrapper(int&& x) {
  return{ std::move(x) };
}

void f(wrapper a) { std::cout << std::move(a.x) << std::endl; }
int g() { return 0; }

int main() {
  f(make_wrapper(g()));
}

这些例子有效吗?也就是说,在 f 的执行完成之前,由 g 创建的临时对象是否仍然存在?当 f 将其参数作为参考时会发生什么?

两个代码示例均有效。

在您的代码中创建的唯一临时对象是从 g() 返回的 int、从 make_wrapper 返回的 wrapper 和通过聚合创建的 wrapper -初始化 wrapper{...}.

所有这些都发生在完整表达式的词法上

f(wrapper{g()});

f(make_wrapper(g()));

并且通常临时对象的生命周期结束于创建它们的完整表达式的末尾。因此,在对 f 的调用中,您所有的临时对象都存活到相应行的末尾,并且 none 其中的一些在其使用寿命之外使用。

这条生命周期规则只有少数例外,所有例外都会延长生命周期。实际上,通过聚合初始化将从 g() 返回的临时 int 绑定到 int&& 子对象实际上将临时的生命周期延长到引用的生命周期。

因此

wrapper w{g()};

实际上不会有悬空引用成员,即使在以下语句中也是如此。