5

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

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

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

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

4

2 回答 2

5

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

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

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

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

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

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

于 2012-12-18T17:17:07.310 回答
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 '&&'
}
于 2012-12-18T17:12:57.760 回答