std :: list :: splice,list&& VS列表&

时间:2012-12-18 17:09:35

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

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

我想知道区别的是什么,以及我应该选择哪种方式。

我查看了libstdc ++(GCC编译器使用的标准C ++库)的实现,它使用了list&& amp;内部两种情况下的版本。此外,C ++ 11规范没有提到这个问题。它只提供了两种方法而没有解释它们之间的差异。

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

2 个答案:

答案 0 :(得分:5)

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

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

此外,当你拼接的列表是一个临时对象时,没有必要关心维持它的状态。函数&&版本可能只是从该列表中删除了内容,在整个楼层留下了一团糟。这可能是为了提高效率(但实际上,std::list并没有太多理由)。

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

std::move

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

答案 1 :(得分:3)

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

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 '&&'
}