右值参考作为对象字段

时间:2014-01-02 13:49:57

标签: c++ c++11 rvalue-reference

#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

这个程序是合法的C ++吗?一旦Foo构造函数完成,bar_会成为悬空参考吗?

如果这在C ++标准方面不合法,那么将右值引用作为字段何时有用?

2 个答案:

答案 0 :(得分:6)

  

Foo构造函数完成后,bar_会成为悬空参考吗?

不完全。它在Bar(1)创建的临时文件被销毁的位置成为悬空参考:在完整表达式Foo foo(Bar(1))的末尾。

这也显示了右值参考成员的用法示例,例如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可以存储右值引用(此处:tuple<vector<int>&&, string&&>),woof的ctor仍然可以使用它来移动v和由std::string{"hello world"}创建的临时引用{{1}}。

答案 1 :(得分:2)

是的,bar_将在构造函数完成后成为悬空引用。

存储引用很少有意义,但有些情况存在。我认为不同类型的参考文献之间没有任何区别。存储的引用引用另一个对象,您需要确保在使用引用时该对象仍然有效。

请注意,如果你写

Bar b( 1 );
Foo foo(std::move(b));

foo不会移动b,它只是存储对它的引用。 b仍然有效且可以使用。只有当Foo成员实际从存储的引用中移出时,才会移动b