【问题标题】:std::list::splice, list&& VS list&std::list::splice, list&& VS list&
【发布时间】:2012-12-05 23:00:53
【问题描述】:

std::list 的一些方法,可能还有其他 STL 容器,在 C++11 中添加了新的重载。我需要的是list::splice()。一种方法采用 list& 参数,另一种采用 list&& 参数。

我想知道有什么区别,我应该更喜欢哪一种。

我查看了 libstdc++(GCC 编译器使用的标准 C++ 库)的实现,它在两种情况下都在内部使用了 list&& 版本。 C++11 规范也没有说明这个问题。它只是提供了 2 种方法,没有解释其中的区别。

您不移动列表本身,也不移动节点(复制它们的指针似乎是将节点从一个列表移动到另一个列表的方式),那么这有什么关系呢?我只有一个想法,也许使用 list&& 就像对编译器的承诺,你不再需要另一个列表,编译器可以保存一些操作,因为它不必保持另一个列表有效......

【问题讨论】:

    标签: c++ stl c++11 move-semantics


    【解决方案1】:

    你不需要太在意。当您传递的参数是右值时,将选择带有 std::list&& 参数的重载 - 通常当它引用的对象是临时对象时。您无需明确说明要使用哪个重载。

    存在这两个版本的函数的原因是为了方便,因此客户端不必在将临时对象传递给 splice 之前从临时对象创建一个 temp std::list 变量(感谢 cmets 中的 @HowardHinnent) .

    此外,当您从中拼接的列表是一个临时对象时,关心维护它的状态是没有意义的。函数的&& 版本可能只是从该列表中撕下胆量,在地板上留下一团糟。这可能是为了提高效率(但实际上,std::list 没有太多理由这样做)。

    如果你有一个std::listother,你知道你永远不会再使用它,你可以自愿说“我不在乎你用它做什么”,使用std::move

    l.splice(pos, std::move(other));
    

    表达式std::move(other) 是一个右值,因此splice 函数会将其视为临时值。

    【讨论】:

      【解决方案2】:

      左值引用绑定到左值,右值引用绑定到右值:

      tyedef std::list<Foo> lt;
      
      lt make_list();
      
      int main()
      {
          lt x;
      
          lt tmp = make_list();
      
          x.splice(tmp);         // needs '&'
          x.splice(make_list()); // needs '&&'
      }
      

      【讨论】:

        猜你喜欢
        • 2020-05-26
        • 2012-03-29
        • 2012-05-13
        • 2020-05-27
        • 2010-09-13
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-07-17
        相关资源
        最近更新 更多