8

In the following the snippet, is the lifetime of the sphere extended in such a way that the value of r is not undefined?

 struct Sphere {
   auto& radius() const { return _radius;}
   float _radius{};
 };
 struct Capsule {
   auto sphere() const { return Sphere{12.0}; }
 };
 auto func() {
   auto capsule = Capsule{};
   const auto& r = capsule.sphere().radius();
   std::cout << r;
 }

I know that const-references extend the life time of a temporary, but I'm not sure what happens if a member of a temporary is bound to.

Note: I'm very suspicious that the equivalent of this snippet is causing a bug for me, but neither Clang nor Visual Studio issues a warning.

Viktor Sehr
  • 12,825
  • 5
  • 58
  • 90
  • Same thing as what I observed in [this question of mine](https://stackoverflow.com/q/38339023/1896169). I think there's a dupe somewhere... – Justin Mar 13 '18 at 20:29
  • Possible duplicate of [const reference to a temporary object becomes broken after function scope (life time)](https://stackoverflow.com/questions/17236007/const-reference-to-a-temporary-object-becomes-broken-after-function-scope-life) – Justin Mar 13 '18 at 20:32
  • 2
    In this case, yes `r` is dangling. The lifetime of the object returned from `sphere()` is not extended to the entire lifetime of `r` – Justin Mar 13 '18 at 20:35
  • @Justin Yes, technically a duplicate but I think the problem is easier to grasp in this question as it does not involve std::map – Viktor Sehr Mar 13 '18 at 21:06
  • This is some of similar with [this question](https://stackoverflow.com/questions/1374468/stringstream-string-and-char-conversion-confusion) – Khurshid Normuradov Mar 14 '18 at 06:25

2 Answers2

5

In order for lifetime extension to occur, the reference must bind to a prvalue (which is then materialized into a temporary object so that the reference has something to bind to). However, capsule.sphere().radius() is not a prvalue; it is an lvalue that refers to Sphere::_radius. Therefore lifetime extension does not occur, and the Sphere object together with its _radius member will be destroyed at the end of the full-expression.

Brian Bi
  • 111,498
  • 10
  • 176
  • 312
1

The lifetime of the temporary Sphere-object is extended only until the completion of the full expression containing the call. The full expression is const auto& r = capsule.sphere().radius(); and not longer, such that r lives longer than the full expression and it's temporary. So I'd clearly vote for undefined behaviour.

Stephan Lechner
  • 34,891
  • 4
  • 35
  • 58