C++ 为什么拼接std::forward_列表的整个列表或范围是线性的?

C++ 为什么拼接std::forward_列表的整个列表或范围是线性的?,c++,list,c++11,forward-list,C++,List,C++11,Forward List,将一个范围从一个列表拼接到另一个列表可以在固定的时间内完成,代价是使size()的复杂性线性化 C++11在std::list的情况下改变了这一点,要求size()为常数时间。例如,这破坏了gcc的实现,请参阅 除了范围splice(),在早期的符合C++03标准的常数时间和所有版本的拼接< 线性> < /p> 拼接整个前向列表是线性的,因为您必须遍历要合并的列表,才能将其最后一个节点链接回要拼接的列表。不过,我不明白为什么范围拼接是线性的 编辑:正如Xeo指出的,基于范围的版本也需要线性时间,

将一个范围从一个列表拼接到另一个列表可以在固定的时间内完成,代价是使
size()
的复杂性线性化

C++11在
std::list
的情况下改变了这一点,要求
size()
为常数时间。例如,这破坏了gcc的实现,请参阅

除了范围
splice()
在早期的符合C++03标准的
实现中,
不能设置恒定时间,还有其他原因吗?

为什么拼接整个列表或范围是线性的

见案例(1)和(3)。另请参见中的23.3.4.6转发列表操作[forwardlist.ops]。
std::forward\u列表
甚至没有实现
size()

我知道forward_list是一个单链接列表,但我不明白为什么不能在固定时间内执行范围
splice_after()
。我可能遗漏了一些琐碎的东西


编辑:好吧,这至少部分是我的误解,我希望4不会保留在源列表中。代码:

#包括
#包括
#包括
使用名称空间std;
无效转储列表(常量转发列表和列表){
用于(字符c:l)

cout在前向链接列表的情况下,如何在恒定时间后进行范围拼接?在源列表中,您只有迭代器。要从源前向链接列表中删除节点,您将需要紧跟在
last
之前的节点,因此您需要在源列表中线性搜索该链接列表节点。因此,为什么需要这样做在
第一个
最后一个


使用整个源列表的版本仍然需要搜索源末尾之前的节点,以便可以修改它以指向目标中拼接后的元素。因此,它还需要源大小的线性时间。

范围拼接是
大小
不可用的唯一原因在以前的C++标准中一直保持一定的时间。事实上,Sun CC编译器选择了<代码>大小>代码>常数时间和所有版本的<代码>拼接< <代码>线性> < /p> 拼接整个前向列表是线性的,因为您必须遍历要合并的列表,才能将其最后一个节点链接回要拼接的列表。不过,我不明白为什么范围拼接是线性的


<>编辑:正如Xeo指出的,基于范围的版本也需要线性时间,因为<代码>最后< /代码>不包括在范围内,它需要从<代码>第一次<代码>中查找“代码之前>迭代器>最后< /COD> .< /P>。您确实应该考虑将此分解成两个问题,因为您似乎在询问C++ 11 STD::列表::和std::forward_list::splice_after()。@DaveS我认为现在讨论这个问题已经太迟了,对不起。请注意,
splice_after
(first,last)
而不是
(first,last)
(顾名思义)。因此,您只需要在
last
之前搜索迭代器,这就是为什么(3)的复杂度是“线性in
std::distance(first,last)
”。实际的拼接是恒定时间。Hrm,你是对的。我在
函数将元素立即放置在设计迭代器之后(比较insert\u after to insert)后实现了
(first,last)
@DaveS好的,你的回答帮助我认识到了我的误解,谢谢!@DaveS好的,我发布了一个新问题,说明了我的问题:请参阅我对Dave关于为什么范围拼接是线性的回答的评论。@MarkB投了赞成票,谢谢!你的回答也很好地说明了我的误解。请检查我问题底部的更新。@MarkB好的,我有e发布了一个新问题,显示了我的问题:@Xeo OK,我发布了一个新问题,显示了我的问题: