【问题标题】:Extension of the lifetime of a temporary with an rvalue reference使用右值引用延长临时对象的生命周期
【发布时间】:2025-12-29 03:55:12
【问题描述】:

According to another answer,如果引用它的表达式是 xvalue 表达式,则右值引用不会延长临时变量的生命周期。由于std::move 返回一个右值引用,调用它的表达式是一个xvalue,所以下面的结果是一个悬空引用:

int main()
{
  std::string&& danger = std::move(get_string());  // dangling reference !
  return 0;
}

没关系。 std::move 在这里没有意义;它已经是一个右值了。

但我在这里画了一个空白。这与将 xvalue 表达式作为参数传递、std::move 和右值引用的完全标准用法有何不同?

void foo(const std::string& val);
// More efficient foo for temporaries:
void foo(std::string&& val);

int main()
{
  std::string s;
  foo(std::move(s)); // Give up s for efficiency
  return 0;
}

对于右值引用参数是否有特殊规则可以延长临时变量的生命周期,无论它是纯右值还是 xvalue?还是 std::move 调用表达式只是一个 xvalue,因为我们传递给它的东西已经是一个右值?我不这么认为,因为它无论如何都会返回一个右值引用,这是一个 xvalue。我在这里很困惑。我觉得我错过了一些愚蠢的东西。

【问题讨论】:

  • 不相关:如果函数 foo 要复制或移动任一方式,您可能只想按值获取参数,让编译器进行复制或移动。
  • 关于您的第一个示例的注释:std::move(get_string()) 不再是临时表达式。临时表达式是get_string(),但随后您将其转换。所以关于临时表达式绑定到引用的规则不再适用。

标签: c++ c++11 rvalue-reference move-semantics


【解决方案1】:

您的第二个示例不是传递对临时变量的引用,而是传递对变量 s 的引用,该变量一直持续到 main() 结束。

如果是(例如foo(std::move(get_string()));),那么临时的生命周期将持续到完整表达式的结尾 - 在函数返回之后。因此在foo 中使用它是非常安全的。只有当foo 存储了一个指向其参数的引用/指针,而其他东西稍后会尝试使用它时,才会有危险。

【讨论】:

  • 但是取右值的地址是非法的。
  • @user1095108 但val 不是函数foo(std::string&& val) 内的右值。它是“右值引用”类型的左值。在s 的生命周期结束之前,获取其地址并使用其地址是完全合法的。
【解决方案2】:

这里不需要延长任何生命周期:有问题的对象会持续到main 的结尾,也就是foo 的结尾。

【讨论】:

  • 确实...在给定的代码中甚至没有任何临时代码。
最近更新 更多