像这样的签名有效的用例是什么?:
T&& foo();
还是右值引用仅用作参数?
如何使用这样的功能?
T&& t = foo(); // is this a thing? And when would t get destructed?
答案 0 :(得分:18)
对于自由函数,返回右值引用没有多大意义。如果它是一个非静态的本地对象,那么您永远都不想返回对其的引用或指针,因为在函数返回后它将被销毁。不过,将右值引用返回给传递给函数的对象可能是有意义的。这是否真的取决于用例。
可以从返回右值引用中大大受益的一件事是临时对象的成员函数。可以说你有
class foo
{
std::vector<int> bar;
public:
foo(int n) : bar(n) {}
std::vector<int>& get_vec() { return bar; }
};
如果愿意
auto vec = foo(10).get_vec();
您必须复制,因为get_vec
返回一个左值。如果您改为使用
class foo
{
std::vector<int> bar;
public:
foo(int n) : bar(n) {}
std::vector<int>& get_vec() & { return bar; }
std::vector<int>&& get_vec() && { return std::move(bar); }
};
然后vec
将能够移动get_vec
返回的向量,从而节省了昂贵的复制操作。
答案 1 :(得分:4)
T&& t = foo(); // is this a thing? And when would t get destructed?
右值引用实际上类似于左值引用。考虑一下您的示例,就像普通参考文献一样:
T& foo();
T& t = foo(); // when is t destroyed?
答案是,只要对象是生命,t
仍然有效。
相同的答案仍然适用于右值参考示例。
但是...返回右值引用有意义吗?
有时候,是的。但是很少。
考虑这一点:
std::vector<int> v = ...;
// type is std::tuple<std::vector<int>&&>
auto parameters = std::forward_as_tuple(std::move(v));
// fwd is a rvalue reference since std::get returns one.
// fwd is valid as long as v is.
decltype(auto) fwd = std::get<0>(std::move(parameters));
// useful for calling function in generic context without copying
consume(std::get<0>(std::move(parameters)));
是的,有例子。在这里,另一个有趣的地方:
struct wrapper {
auto operator*() & -> Heavy& {
return heavy;
}
auto operator*() && -> Heavy&& {
return std::move(heavy);
}
private:
Heavy instance;
};
// by value
void use_heavy(Heavy);
// since the wrapper is a temporary, the
// Heavy contained will be a temporary too.
use_heavy(*make_wrapper());
答案 2 :(得分:0)
我认为一个用例是明确允许“空”一些非局部变量。也许是这样的:
class Logger
{
public:
void log(const char* msg){
logs.append(msg);
}
std::vector<std::string>&& dumpLogs(){
return std::move(logs);
}
private:
std::vector<std::string> logs;
};
但是我承认我现在做了这个,我从来没有实际使用过,它也可以像这样完成:
std::vector<std::string> dumpLogs(){
auto dumped_logs = logs;
return dumped_logs;
}