3

Is the following use of p within main safe? I believe binding the temporary produced by mk_pair has its lifetime extended to that of p, but how about the temporary objects created by Wrap{1} and Wrap{2}?

struct Wrap { int &&x; };

struct Pair { Wrap &&w1, &&w2; };

Pair mk_pair(Wrap &&w1, Wrap &&w2) { return Pair{std::move(w1),std::move(w2)}; }

int main(int argc, char *argv[])
{
  Pair &&p = mk_pair(Wrap{1},Wrap{2});
  std::cout << p.w1.x << ' ' << p.w2.x << '\n';
  return 0;
}
user2023370
  • 10,488
  • 6
  • 50
  • 83

2 Answers2

4

No. Wrap{1} and Wrap{2} are not bound to automatic references in main, so they are destructed at the end of the line.

The Pair returned from mk_pair has its lifetime extended to that of p, but its references are dangling.

Quentin
  • 62,093
  • 7
  • 131
  • 191
2

This is undefined behavior. In

mk_pair(Wrap &&w1, Wrap &&w2)

you take w1 and w2 as rvalue references, which is okay, you extend the life into the function. Then you return an object that refers to those references. The problem with that is when the expression ends, those temporaries you passed by reference, are destroyed. That means you know have references to refer to expired objects and using those is undefined behavior.

gsamaras
  • 71,951
  • 46
  • 188
  • 305
NathanOliver
  • 171,901
  • 28
  • 288
  • 402