user3882729
user3882729

Reputation: 1534

c++ object lifetime extension rules with member initializers

In this talk, the author mentions lifetime extension rules extend to member initializers based on the standard. I see the opposite though, i.e. ~Y is called before "Hello" is printed below. Is the author referring to something else?

#include <iostream>
using namespace std;

struct Y {
   ~Y() { 
      cout << __PRETTY_FUNCTION__ << "\n";
   }
   Y() { 
      cout << __PRETTY_FUNCTION__ << "\n";
   }
};

struct X {
   ~X() { 
      cout << __PRETTY_FUNCTION__ << "\n";
   }
   X(const Y& y) : ref(y) { 
      cout << __PRETTY_FUNCTION__ << "\n";
   }
   const Y &ref;
};

Y gety() { 
   return {};
}

X getx() { 
   return gety();
}

int main() {
   const X &ref = X{Y{}};
   cout << "Hello\n";
}

The output is

Y::Y()
X::X(const Y&)
Y::~Y()
Hello
X::~X()

Edit: I see a difference with the following update that does aggregate initialization

struct X {
   ~X() { 
      cout << __PRETTY_FUNCTION__ << "\n";
   }
   /*
   X(const Y& y) : ref(y) { 
      cout << __PRETTY_FUNCTION__ << "\n";
   }
   */
   const Y &ref;
};

int main() {
   const X &ref = X{Y{}};
   cout << "Hello\n";
}

in which case the output is

Y::Y()
Hello
X::~X()
Y::~Y()

Upvotes: 2

Views: 46

Answers (1)

user17732522
user17732522

Reputation: 76698

It applies only in the case of aggregate initialization, because otherwise there is a constructor call and the prvalue would be bound to the reference parameter of that constructor, not directly to the reference member.

Also, it does not apply to aggregate initialization with parentheses instead of braces in C++20 and later. (There is a specific exception for this case.)

Upvotes: 6

Related Questions