I was shown the following example in chat:
#include <iostream>
struct foo { ~foo() { std::cout << "destroying!\n"; } };
const foo& func(const foo& a, const foo&) { return a; }
int main()
{
foo x;
const foo& y = func(foo(), x);
std::cout << "main\n";
}
Output:
destroying!
main
destroying!
It appears to demonstrate that the lifetime of the foo
temporary is not extended to entirety of main
, even though it gets bound to a ref-to-const
in that scope.
Presumably, then, the lifetime extension only "works once"; that is, it is applied when func
's arguments are initialised, but isn't passed on through consecutive bindings.
Is my interpretation correct? If so (and if any individual paragraph is directly applicable) what's the standard wording that defines this behaviour?
You're almost right. This behaviour actually comes from the function call specifically, not because of any sort of "only works once" rule.
Here's the wording for the whole lifetime extension "feature", with the pertinent rule emphasised in bold:
[C++11: 12.2/5]:
[..] The temporary to which the reference is bound or the temporary that is the complete object of a subobject to which the reference is bound persists for the lifetime of the reference except:
- [..]
- A temporary bound to a reference parameter in a function call (5.2.2) persists until the completion of the full-expression containing the call.
- [..]
This is subject of two issue reports, http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#1299 and http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#1568 .
The former issue report, of which I am the reporter, was intended to cover all these cases where a reference is bound to a temporary object, but is not intended to be lifetime-extending. The description in the body of the issue only mentions prvalues being confused with temporary expressions (that actually decide whether lifetime of what they evaluate to is lengthened or not). But lvalue and xvalues are likewise confused with these in the Standard. An example where that happens in the context of static_cast
is issue number #1568 (in which the use of "temporary variable" further confuses the matter).
Actually, this:
A temporary bound to a reference parameter in a function call (5.2.2) persists until the completion of the full-expression containing the call.
Contradicts the other rules in the same paragraph. Because the temporary is bound to both a reference parameter in a function call and to a local automatic reference variable.
The rule which applies here is common sense. The standard is poorly worded, and does in fact guarantee this. But there's no practical way to implement it.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With