【问题标题】:Binding of Type&& (rvalue reference) to modifiable lvalues and将 Type&& (右值引用)绑定到可修改的左值和
【发布时间】:2013-08-28 19:30:10
【问题描述】:

加深了我的 C++ 知识,找到了解释右值引用 http://blogs.msdn.com/b/vcblog/archive/2009/02/03/rvalue-references-c-0x-features-in-vc10-part-2.aspx 的优秀文章(文章有些过时,发表于 2009 年)。

在文章中有几行应该出错

// original
   string&& i = modifiable_lvalue;         // Line 26

    string&& j = const_lvalue;              // Line 27 - ERROR

    string&& k = modifiable_rvalue();       // Line 28

    string&& l = const_rvalue();            // Line 29 - ERROR

但是,在 Visual Studio 2012 string&& i = modifiable_lvalue; // Line 26 - ERROR 中也会出错!!!

错误 C2440: 'initializing' : 无法从 'std::string' 转换为 'std::string &&'

根据文章

可修改的右值引用,Type&&,愿意绑定到可修改的 左值和可修改的右值

这完全应该发生在第 26 行。那我为什么会收到错误消息??
谢谢!

编辑:发现与此主题相关的非常有趣的文章:http://web.archive.org/web/20120529225102/http://cpp-next.com/archive/2009/09/move-it-with-rvalue-references/#fn:insertionsort。未来的读者可能会发现它很有帮助。

【问题讨论】:

  • @nosid:不,问题中的代码是文章中代码的逐字复制。

标签: c++ c++11


【解决方案1】:

文章错了,右值引用不能绑定到左值。现在有引用折叠的概念(此处不适用),它允许在模板参数中进行类似的操作:

template <typename T>
void f(T&& x);

参数x 可以绑定到左值或右值,但是当它绑定到左值时,它不是右值引用,而是推导的类型TU&amp;U&amp; &amp;&amp; 中的两个引用折叠成左值引用,因此参数类型为U&amp;rvalue-reference 被丢弃)。这通常称为通用参考

同样,这适用于您从文章中引用的代码,这是不正确的。

请注意,文章写于 2009 年,当时的标准草案可能有文章中描述的行为。从 2009 年到 2011 年,当现行标准最终被接受时,发生了一些变化。

【讨论】:

  • +1。我相信 有一段时间(= 标准草案的版本),r-value refs 也可以绑定到 l-values。所以它可能只是基于那个版本。
  • 所以,基本上非常量 Type&& 只能绑定到可修改的右值。而 const Type&& 可以绑定到 const 和非 const 右值。最重要的是string&amp; c = modifiable_rvalue(); 也是如此 - 即 Type& 可以绑定到 mod。右值。
  • @DavidRodríguez-dribeas: const 左值引用有时可以直接绑定到右值,可能不会创建临时值。同样,有时可能会创建一个临时对象来间接绑定右值引用。见 8.5.3。
  • @user1131467:不,我的困惑是没有阅读 C++11 中的部分,正如我已经告诉你的那样。我更熟悉的 C++03(如果没有别的因为已经知道了很长时间)需要您提供的示例中的副本。引用直接绑定到左值或(可能)为右值创建临时值,但是(8.5.3/5b2):用于制作副本的构造函数应可调用,无论副本是否实际上已经完成了。我已经阅读了 C++11 标准并且已经改变,现在引用直接绑定到类右值。
  • @newprint:允许 C++ 编译器将格式错误的程序编译为扩展。 MSVC 支持将非 const 左值引用绑定到右值作为这样的扩展。这再次引起了微软的争议和投诉,但他们没有考虑更改它,因为它会破坏依赖此扩展的旧 Windows 特定代码。
【解决方案2】:

文章不正确。您需要使用 static_cast&lt;std::string&amp;&amp;&gt; 或更惯用的 std::move() 将其显式转换为右值引用:

std::string&& i = std::move( modifiable_lvalue );

这段代码告诉编译器(和读者!)你承诺使用modifiable_lvalue

【讨论】:

    猜你喜欢
    • 2011-11-04
    • 2017-12-06
    • 2014-10-31
    • 2017-04-13
    • 2014-01-02
    • 1970-01-01
    • 1970-01-01
    • 2018-09-30
    相关资源
    最近更新 更多