函数返回rvalue参考是否有意义



对于这样的签名,有效的用例是什么?:

T&& foo();

或RVALUE REF仅用于参数?

如何使用这样的函数?

T&& t = foo(); // is this a thing? And when would t get destructed?

对于免费函数,返回rvalue参考并没有多大意义。如果它是一个非静态本地对象,那么您永远不想返回参考或指针,因为函数返回后将被破坏。不过,返回对您传递给该功能的对象的RVALUE引用可能是有意义的。这确实取决于用例是否有意义。

返回rvalue参考可以大大受益的一件事是临时对象的成员函数。可以说你有

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返回lvalue。如果您使用

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返回的向量,您可以节省一个昂贵的复制操作。

T&& t = foo(); // is this a thing? And when would t get destructed?

RVALUE参考确实与LVALUE参考相似。想一想您的示例是正常的参考:

T& foo();
T& t = foo(); // when is t destroyed?

答案是,只要对象是指生命,t仍然有效。

相同的答案仍然适用于您的rvalue参考示例。


但是...返回rvalue参考是否有意义?

有时,是的。但是很少。

考虑一下:

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());

我认为用例是明确授予"空"某些非本地变量的权限。也许这样的东西:

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;
}

相关内容

最新更新