#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 ++标准方面不合法,那么将右值引用作为字段何时有用?
答案 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
。