C++ 什么样的代码需要知道右值引用?

C++ 什么样的代码需要知道右值引用?,c++,c++11,rvalue-reference,C++,C++11,Rvalue Reference,我看到很多人在理解右值引用时遇到问题。“普通”C++代码(例如,使用标准库但不实现它)需要在新标准出来后知道R值引用,或者人/代码是否仅仅假定R值引用不存在?rvalue引用主要涉及库实现者还是所有程序员?大多数人可以假装它们不存在,他们只会看到好处(在某些情况下代码速度更快) 请记住,C++0x将是99.9%向后兼容的,因此所有现有代码仍然可以工作,这意味着您可以继续编写C++0x代码,就像编写C++03一样 如果你想从右值引用中获益,那么你当然需要了解它们,但大多数情况下,这只是图书馆作者关

我看到很多人在理解右值引用时遇到问题。“普通”C++代码(例如,使用标准库但不实现它)需要在新标准出来后知道R值引用,或者人/代码是否仅仅假定R值引用不存在?rvalue引用主要涉及库实现者还是所有程序员?

大多数人可以假装它们不存在,他们只会看到好处(在某些情况下代码速度更快)

请记住,C++0x将是99.9%向后兼容的,因此所有现有代码仍然可以工作,这意味着您可以继续编写C++0x代码,就像编写C++03一样


如果你想从右值引用中获益,那么你当然需要了解它们,但大多数情况下,这只是图书馆作者关心的问题。

至少在大多数情况下,你可以忽略它们,只要你愿意。(重新)编写标准库以使用它们允许进行大量优化和一些新功能,但主要目标之一是现有代码应该继续正常工作(尽管在某些情况下,速度更快)

支持现有代码意味着,任何人只要觉得它可以继续以以前的方式编写代码,而且也不会受到影响(同样,除了他们使用的一些库“东西”可能更快)

同时,有些人可能想学习一些经验法则,让他们能够简单地使用右值引用,这是有充分理由的。一个明显的例子是人们现在经常遇到的问题:他们有一个类,复制对象实际上没有意义,但他们仍然希望能够将这些对象放在一个集合中(例如,向量)

他们可以通过使该类对象可移动但不可复制来实现这一点。这方面的一个主要例子是streams——现在,您不能将任何类型的iostream对象放入集合中,但在C++0x中,您可以这样做


另一种可能是使用“完美转发”。这可以让我们更容易地将以前的许多独立功能整合到一个非常简单的前端中,这些前端都可以转发到真正的工作。您始终可以不使用此函数,但在某些情况下,它可以使代码的重复性大大降低。

您可能不需要了解右值引用,因为编写某个函数时需要使用右值引用,但您可能会从理解移动语义、了解移动构造函数等方面获益。如果你想使用unique_ptr(并且因为它没有引用计数而获得性能优势),那么你几乎肯定需要使用std::move(比如说,在集合中输入和输出),我无法想象用典型的二年级学生处理指针的“如果我在这里输入a&或a*会怎么样?”


我刚刚在柏林的欧洲科技展上做了一个“VC++的新功能是C++0x”的演讲,其中有一张关于右值引用的幻灯片,我基本上说“你需要知道它们在这里,因为它们使STL的方式更快”,但我没有进一步钻研。这似乎比我在其他演讲中所用的(较长的)变体更容易被与会者接受。

如果你没有实现一个值语义类,你真的不需要知道


编辑:或完美转发。但这同样主要是图书馆的使用。

在GMan(又名gmannickg)的博客文章中,我没有看到有什么不同意的地方:

小结:任何了解复制和交换(以及通常的三个规则)的人都应该了解移动语义(以及右值引用),因为最佳实践习惯用法会因此发生变化。因此,我认为,任何人都关心C++。 我认为你不必知道,因为当然复制和交换仍然有效,它仍然是异常安全的,等等。我想有人会争论“普通”C++代码和程序员是否需要知道复制和交换。我希望答案是“嗯,嗯,很明显”,但你永远不知道

当然,可以开始使用C++0x的点会因地而异。很快放弃C++03可能不是一个好主意

例如,如果您可以依赖移动分配,则在对复制省略无效的上下文中按值返回大量集合将成为更好的选择。这不是一个在C++03中无效的东西在C++0x中变得有效的情况,而是在C++03中速度非常慢的代码,您可以在C++0x中处理(即使只使用位置良好的
交换
),变得很好。所以,如果你假装右值引用不存在,你将继续处理一些你不需要的东西。如果您进行了跳转,那么它可能会干净地返回到C++03,但运行速度很慢,这是一种痛苦

因此,明智的做法可能是了解它,并在许多情况下假装它不存在。

我同意,右值引用并不是每个人的一杯茶——这杯茶相当大


因此,我告诉C++0x的学习者,开始学习和利用右值引用的最佳方法是使用STL并随着时间的推移接受其设计模式。这很可能会使您受益于右值引用,而不必事先完全理解它们。

Scott Meyers将C++0x特性分为:

  • 每个人都有自己的特色
  • 类作者的特性
  • 为图书馆作者提供的功能

  • 右值绝对是库作者

    在c++11中,我会通过&&传递我计划“存储”或“消费”的任何内容。这导致了最有效的代码,但是“中断”LValuy兼容性,迫使我考虑每个方法有两个(或更多)版本。不幸的是,你得到了右值和常数&a的大量排列
    template<typename T>
    T copy( const T& v ) { return v; }
    
    class test  {
      public:
        test(){...};
        test( test&& t ){...}
    
      private:
        template<typename T>
        friend T copy(const T&t);
    
        test& operator=(const test&); // not implemented
        test( const test& t ){...}
    
        std::vector<char> large_data;
    };
    
    int main( int argc, char** argv ) {
      test x;
      test y = copy(x);
      test z = x; // error, test(const test&) is private...
      return 0;
    }