lundi 3 août 2015

What determines when the lifetimes of temporaries get extended into const references or rvalue references?

Given:

struct hurg { ... };

hurg get_hurg() { return hurg(); }
hurg&& get_mhurg() { return hurg(); }

My understanding and experimenting shows that the following is not undefined behavior:

{
    const hurg& a = get_hurg(); 
    hurg&& b = get_hurg();
    const hurg& c = get_mhurg(); 
    hurg&& d = get_mhurg();
    // do stuff with a, b, c, d
}
// a, b, c, d are now destructed

That is, the lifetime of the temporary hurg object returned by get_hurg() and get_mhurg() is extended until the end of the scope.

However, in the case of (function from here):

template <typename T>
auto id(T&& x) -> decltype(auto) { return decltype(x)(x); }    

Using it like:

{
    const hurg& x = id(hurg()); 
    // the hurg() 'x' refers to is already destructed

    hurg&& y = id(hurg());
    // the hurg() 'y' refers to is already destructed

    // undefined behavior: use 'x' and 'y'
}

In this case, the lifetime of the hurg is not extended.

What determines when the lifetime of temporaries is extended in general? And, in particular, when is it safe to bind the result of a function to a const lvalue ref or an rvalue ref?

And more specifically, what precisely is happening in the id case?

Aucun commentaire:

Enregistrer un commentaire