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

MW_*_*dev 27 c++ rvalue lvalue overload-resolution c++11

我试图理解为什么有人会编写一个带有const右值引用函数.

在下面的代码示例中,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;
}
Run Code Online (Sandbox Code Playgroud)

rek*_*o_t 30

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

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

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

template <typename T> void foo(const T& bar) { /* ... */ }
Run Code Online (Sandbox Code Playgroud)

并调用函数:

foo(createVector());
Run Code Online (Sandbox Code Playgroud)

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

template <typename T> void foo(const T&&) = delete;
Run Code Online (Sandbox Code Playgroud)

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

  • 这并不能说明为什么const rvalues本身是有用的,只是为什么你可能需要const rvalue引用. (3认同)
  • @reko_t:对你的回答进行小修正.这不会改变你的结论.但是左值不能绑定到const右值引用.最初他们可以.但这些规则在2009年春季发生了变化,以至于它们不能.这个规则的一个明显的例外是在对"T &&"(非常量)形式的模板参数进行推导时.这个表单是特殊的,并且将绑定到左值(否则完美转发将不起作用).话虽如此,我完全同意您的用例:http://stackoverflow.com/questions/4938875/do-rvalue-references-to-const-have-any-use/4940642#4940642 (2认同)