'Aggregate reference member and temporary lifetime
Given this code sample, what are the rules regarding the lifetime of the temporary string being passed to S.
struct S
{
// [1] S(const std::string& str) : str_{str} {}
// [2] S(S&& other) : str_{std::move(other).str} {}
const std::string& str_;
};
S a{"foo"}; // direct-initialization
auto b = S{"bar"}; // copy-initialization with rvalue
std::string foobar{"foobar"};
auto c = S{foobar}; // copy-initialization with lvalue
const std::string& baz = "baz";
auto d = S{baz}; // copy-initialization with lvalue-ref to temporary
According to the standard:
N4140 12.2 p5.1 (removed in N4296)
A temporary bound to a reference member in a constructor’s ctor-initializer (12.6.2) persists until the constructor exits.
N4296 12.6.2 p8
A temporary expression bound to a reference member in a mem-initializer is ill-formed.
So having a user defined constructor like [1] is definitively not what we want. It's even supposed to be ill-formed in the latest C++14 (or is it?) neither gcc nor clang warned about it.
Does it change with direct aggregate initialization? I looks like in that case, the temporary lifetime is extended.
Now regarding copy-initialization, Default move constructor and reference members states that [2] is implicitly generated. Given the fact that the move might be elided, does the same rule apply to the implicitly generated move constructor?
Which of a, b, c, d has a valid reference?
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|
