C ++ 0x const RValue引用作为函数参数

时间:2011-06-10 14:09:39

标签: c++ c++11 lvalue rvalue overload-resolution

我试图理解为什么有人会编写一个带 const rvalue reference 的函数。

在下面的代码示例中,const rvalue引用函数的用途是什么(返回“3”)。 为什么重载决策首选const Rvalue高于const LValue引用函数(返回“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;
}

2 个答案:

答案 0 :(得分:30)

Lvalues强烈倾向于绑定到左值引用,类似地,右值引用强烈倾向于绑定到右值引用。可修改的表达式弱选择绑定到非const引用。

因此,当您的编译器执行重载解析时,它会检查是否存在带有右值引用的重载,因为这是强烈的首选。在这种情况下,因为experssion是一个可修改的rvalue,所以rvalue引用超载获胜。

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

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

用以下方法调用函数:

foo(createVector());

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

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

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

答案 1 :(得分:2)

重载分辨率更喜欢const rvalue而不是const lvalue,因为它是一个rvalue并且你将它绑定到一个右值引用,但你必须在两种情况下都添加const,所以rvalue reference绝对是首选。

这些事情通常毫无意义 - 最好让它们绑定到const lvalue重载。 const rvalues没有任何实际用途。