Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

rvalue reference as an object field

#include <iostream>  
struct Bar
{
    int nb_;
    Bar(int nb) :nb_(nb){}
    ~Bar()
    {
        std::cout << "~Bar" << "\n";
    }
}; 

struct Foo
{    
    template<class T>
    Foo(T&& param) :bar_(std::move(param))
    {
        std::cout << "Foo" << "\n";
    } 
    ~Foo()
    {
        std::cout << "~Foo" << "\n";
    }

    Bar&& bar_;
};

int main()
{       
    { 
        Foo foo(Bar(1));
    }

    std::cin.ignore();
}

//Output:
Foo
~Bar 
~Foo

Is this program is legal C++? Does bar_ will become a dangling reference once the Foo constructor will be finished?

If this is not legal in term of C++ standard, when is it useful to have a rvalue reference as a field ?

like image 386
Guillaume Paris Avatar asked Feb 14 '23 06:02

Guillaume Paris


1 Answers

Does bar_ will become a dangling reference once the Foo constructor will be finished?

Not quite. It becomes a dangling reference at the point where the temporary created by Bar(1) is destroyed: at the end of the full-expression Foo foo(Bar(1)).

That also shows a usage example of rvalue reference members, for example forward_as_tuple:

struct woof
{
    using my_tuple = std::tuple<std::vector<int>, std::string>;
    my_tuple m;

    woof(my_tuple x) : m(std::move(x)) {}
};

std::vector<int> v{1,2,3,4,5};
woof w( forward_as_tuple(std::move(v), std::string{"hello world"}) );

forward_as_tuple can store rvalue references (here: in a tuple<vector<int>&&, string&&>), which still can be used by the ctor of woof to move v and the temporary created by std::string{"hello world"}.

like image 146
dyp Avatar answered Feb 23 '23 13:02

dyp