Is it possible to change the temporary object and to pass it as an argument?
struct Foo {
Foo& ref() { return *this; }
Foo& operator--() { /*do something*/; return *this; }
// another members
};
Foo getfoo() { return Foo(); } // return Foo() for example or something else
void func_val(Foo x) {}
void func_ref(const Foo & x) {}
int main() {
func_val(--getfoo()); // #1 OK?
func_ref(getfoo()); // #2 OK?
func_ref(getfoo().ref()); // #3 OK?
// the following line is a real example
// using --vector.end() instead of --getfoo()
func_ref(--getfoo()); // #4 OK?
const Foo & xref = --getfoo(); // Does const extend the lifetime ?
func_ref(xref); // #5 OK?
func_val(xref); // #6 OK?
}
It is known that assigning a temporary object to the const reference extends the lifetime of this temporary object. And what about #4 and #5 lines of my code?
Is it true that reference x is always valid in the function func_ref?
The thing is that operator– returns some reference and the compiler does not see any relation between this reference and the temporary we created.
Yes, OK. The
operator--is a member-function, which is called, and which returns itself (and lvalue referring to itself). The object is then copied into the parameter offunc_val. Notice that return value optimization is not allowed to apply, since the temporary created bygetfoo()was previously bound to a reference.Yes, OK. The call
getfoo()returns a temporary which is bound to the const reference. A copy constructor is required, but the call it it may be optimized out by the implementation. The temporary persists until the end of the full-expression containing the call tofunc_ref(the whole expression statement here).Yes, OK. No copy constructor required, as we bind the const reference not to a temporary but to the lvalue representing the object itself.
That is not required to work. Think of a situation where
vector.end()returns aT*(allowed). You are not allowed to modify rvalues of non-class type, so in that case, this would be ill-formed.Yes, OK. The argument is evaluated as in
#1, but the resulting lvalue is directly passed and the const reference is bound to it. In this sense it’s equal to#3(except for the decrement side effect).The Standard wording is not entirely clear. It surely intends to only extend lifetime of objects not yet bound to a reference. But in our case,
--getfoo()yields an lvalue refering to a temporary object which was previously bound to a reference. It may be worth submitting a defect report to the committee (i may also have missed wording that requires the temporary object to not be bounded to a reference yet).In any case, the intended behavior is to destruct the temporary that results from
getfoo()at the end of initializingxref, soxrefwill become a dangling reference.Exactly (but applies only to the initialization of
xrefwhich will go mad. In all other cases, the intended behavior you want (or what i believe you want) is achieved).