Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Extension of the lifetime of a temporary with an rvalue reference

According to another answer, an rvalue reference will not extend the lifetime of a temporary if the expression referring to it is an xvalue expression. Since std::move returns an rvalue reference, the expression of calling it is an xvalue and so the following results in an a dangling reference:

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

That's fine. The std::move doesn't make sense here; it is already an rvalue.

But here's where I'm drawing a blank. How is this different to passing an xvalue expression as an argument, completely standard use of std::move and rvalue references?

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;
}

Is there a special rule for rvalue reference arguments that will extend the lifetime of a temporary regardless of whether it is an prvalue or xvalue? Or is the std::move calling expression only an xvalue because we passed it something that was already an rvalue? I don't think so because it returns an rvalue reference anyway, which is an xvalue. I'm confused here. I think I'm missing something silly.

like image 439
Joseph Mansfield Avatar asked Nov 27 '12 13:11

Joseph Mansfield


1 Answers

Your second example is not passing a reference to a temporary, it's passing a reference to the variable s, which lasts until the end of main().

If it were (e.g. foo(std::move(get_string()));), then the temporary's lifetime lasts until the end of the full expression - after the function has returned. It's therefore quite safe to use it within foo. There is only a danger if foo stores a reference/pointer to its argument, and something else tries to use it later.

like image 139
Mike Seymour Avatar answered Sep 24 '22 21:09

Mike Seymour