函数返回右值引用有意义吗?

Mar*_* B. 26 c++

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

T&& foo();
Run Code Online (Sandbox Code Playgroud)

还是右值引用仅打算用作参数?

如何使用这样的功能?

T&& t = foo(); // is this a thing? And when would t get destructed?
Run Code Online (Sandbox Code Playgroud)

Nat*_*ica 19

对于自由函数,返回右值引用没有多大意义。如果它是一个非静态的本地对象,则您永远不想返回对其的引用或指针,因为在函数返回后它将被销毁。不过,将右值引用返回到传递给函数的对象可能是有意义的。它是否真正取决于用例。

可以从返回右值引用中大大受益的一件事是临时对象的成员函数。可以说你有

class foo
{
    std::vector<int> bar;
public:
    foo(int n) : bar(n) {}
    std::vector<int>& get_vec() { return bar; }
};
Run Code Online (Sandbox Code Playgroud)

如果你这样做

auto vec = foo(10).get_vec();
Run Code Online (Sandbox Code Playgroud)

您必须复制,因为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); }
};
Run Code Online (Sandbox Code Playgroud)

这样vec便可以移动返回的向量,get_vec从而节省了昂贵的复制操作。

  • `std :: vector &lt;int&gt; get_vec()&amp;&amp; {返回std :: move(bar); }`在这种情况下最终会更好地达到999/1000。你能提出一个更好的例子吗? (4认同)

Gui*_*cot 5

T&& t = foo(); // is this a thing? And when would t get destructed?
Run Code Online (Sandbox Code Playgroud)

右值引用实际上类似于左值引用。考虑一下您的示例,就像普通引用一样:

T& foo();

T& t = foo(); // when is t destroyed?
Run Code Online (Sandbox Code Playgroud)

答案是,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)));
Run Code Online (Sandbox Code Playgroud)

是的,有例子。在这里,另一个有趣的是:

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());
Run Code Online (Sandbox Code Playgroud)


Qui*_*mby 1

我认为一个用例是明确授予“清空”某些非局部变量的权限。也许是这样的:

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;
};
Run Code Online (Sandbox Code Playgroud)

但我承认这是我现在编造的,我从未真正使用过它,它也可以这样做:

std::vector<std::string> dumpLogs(){
    auto dumped_logs = logs;
    return dumped_logs;
}
Run Code Online (Sandbox Code Playgroud)