【问题标题】:C++0x const RValue reference as function parameterC++0x const RValue 引用作为函数参数
【发布时间】:2011-09-12 13:06:30
【问题描述】:

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

在下面的代码示例中,const rvalue 引用函数的用途是什么(返回“3”)。 以及为什么重载解析优先于 const LValue 引用函数(返回“2”)之上的 const Rvalue。

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

【问题讨论】:

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


【解决方案1】:

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

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

实际上有用于 const 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(),你的编译器会出错。这是实现此类功能的唯一方法,因此有时很有用。

【讨论】:

  • 感谢您的深入回答。当您说:“左值强烈倾向于绑定到左值引用”时,您是什么意思?我不认为 LValues 可以绑定到 RValues。我误会你了吗?
  • 左值可以绑定到常量右值引用。 Anything 可以绑定到 const 左值引用以及 const 右值引用。
  • 这并没有真正说明为什么 const rvalues 本身有用,只是为什么您可能需要 const rvalue 引用。
  • @reko_t:对您的回答稍作更正。这不会改变你的结论。但是左值不能绑定到 const 右值引用。本来他们可以的。但是规则在 2009 年春天发生了变化,因此他们不能。该规则的一个明显例外是在对T&amp;&amp;(非常量)形式的模板参数进行推导时。这种形式很特殊,将绑定到左值(否则完美转发将不起作用)。话虽如此,我完全同意你的用例:stackoverflow.com/questions/4938875/…
  • DeadMG,这就是 OP 的要求:I am trying to understand why someone would write a function that takes a const rvalue reference
【解决方案2】:

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

这样的事情通常是没有意义的——最好让它们绑定到 const 左值重载。 const rvalues 没有任何实际用途。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-01-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-10-31
    • 2012-02-25
    • 2020-07-20
    相关资源
    最近更新 更多