27

I am trying to understand why someone would write a function that takes a const rvalue reference.

In the code example below what purpose is the const rvalue reference function (returning "3"). And why does overload resolution preference the const Rvalue above the const LValue reference function (returning "2").

#include <string>
#include <vector>
#include <iostream>

std::vector<std::string> createVector() { return std::vector<std::string>(); } 

//takes movable rvalue
void func(std::vector<std::string> &&p) { std::cout << "1"; }

//takes const lvalue
void func(const std::vector<std::string> &p)  { std::cout << "2"; }

//takes const rvalue???
//what is the point of const rvalue? if const I assume it is not movable?
void func(const std::vector<std::string> &&p) { std::cout << "3"; }

int main()
{
    func(createVector());
    return 0;
}
4

2 回答 2

30

左值非常喜欢绑定到左值引用,同样,右值引用也非常喜欢绑定到右值引用。可修改表达式较弱地倾向于绑定到非常量引用。

因此,当您的编译器进行重载解析时,它会检查是否存在采用右值引用的重载,因为这是强烈推荐的。在这种情况下,由于表达式是可修改的右值,所以右值引用重载获胜。

实际上有用于 const rvalue 引用,它们可用于确保某些内容绑定到 rvalue。请记住,右值绑定到 const 左值引用,因此如果您这样做了:

template <typename T> void foo(const T& bar) { /* ... */ }

并使用以下方法调用该函数:

foo(createVector());

它工作得很好。但是,有时需要确保您只能将左值传递给函数(对于一个函数就是这种情况std::ref)。您可以通过添加重载来实现此目的:

template <typename T> void foo(const T&&) = delete;

请记住,右值非常喜欢绑定到右值引用,而可修改表达式更喜欢弱绑定到非常量引用。由于我们有一个 const rvalue-reference,它基本上意味着每个 rvalue 都会绑定到 this,因此如果您尝试将 rvalue 传递给foo(),您的编译器会出错。这是实现此类功能的唯一方法,因此有时很有用。

于 2011-06-10T14:30:24.887 回答
2

Overload resolution prefers const rvalue over const lvalue because, well, it's an rvalue and you're binding it to an rvalue reference, but you have to add const in both cases, so rvalue reference definitely preferred.

Such things are generally pointless- it's best to leave them binding to the const lvalue overloads. const rvalues don't have any real use.

于 2011-06-10T14:11:33.640 回答