作为对象字段的右值引用

rvalue reference as an object field

本文关键字:引用 字段 对象      更新时间:2023-10-16
#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++标准方面是不合法的,那么什么时候将右值引用作为字段有用?

一旦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 仍然可以使用它来移动vstd::string{"hello world"} 创建的临时引用。

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

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

请注意,如果您编写

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

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