partition()
和 remove()
函数在 C++ 中有什么区别?
remove()
函数并不会真正删除容器中的任何元素,而是将“已删除”的元素放在元素序列的开头;partition()
函数也会执行相同的操作。
partition()
和 remove()
函数在 C++ 中有什么区别?
remove()
函数并不会真正删除容器中的任何元素,而是将“已删除”的元素放在元素序列的开头;partition()
函数也会执行相同的操作。
使用 remove() 函数会将“已删除”的元素放在序列开头
不是这样的。无论是 remove_if
还是 partition
函数都会将“好”的元素放在序列的前面。而 partition
函数会将“坏”的元素放在后面,而 remove_if
函数没有指定其后面的元素是什么,它可能是坏元素,也可能是任何一个(好或坏)元素的副本。
例如,如果你在偶数上使用 partition
函数对序列 1 2 3 4 5 进行分区,你可能得到 2 4 5 3 1(注意每个元素恰好出现一次),而如果你删除奇数元素,你可能得到 2 4 3 4 5(注意重复元素)。
remove_if
并不把删除的元素放到任何地方;新结尾后面的元素将保留原值,因此有些被删除的元素可能会丢失,有些保留的元素可能会重复。这比partition
更快,并且可以使用前向迭代器完成,而partition
需要双向迭代器。
更新:在 C++0x 中,partition
只需要前向迭代器,但如果迭代器不是双向的,则速度会更慢。
partition
的契约以使用前向迭代器。 - Mike Seymourpartition
比remove_if
快得多。如果要删除的元素位于一个巨大向量的开头,remove_if
会将整个向量向左移动,而partition
只会将要删除的元素与最后一个元素交换。 - aberaudremove
并不会交换任何元素,而只是将谓词(在remove_if
的情况下)为false的元素移动到序列的开头。如果你有一个数组:
a = [1,1,1,2,3]
然后调用 remove(a.begin(),a.end(),1)
,你将得到:
a = [2,3,1,2,3]
之后,remove
返回一个迭代器,这种情况下是第三个元素(如果我没记错的话...)
另一方面,partition
保留了序列的所有原始元素,但改变它们的顺序,使谓词为true的元素放在谓词为false的元素前面。
partition(a.begin(), a.end(), not_equal<int>(1))
得到:
a = [2,3,1,1,1]
std::remove()
返回新的结束迭代器之后留下的内容是不保证的。虽然您展示的结果很可能正确,但并不是保证的。 - sbistd::remove
保证不会改变新结尾迭代器后面的元素(它们仍然可以被访问)。但是标准可能会证明我是错的 :) ... - MartinStettnerstd::vector<std::string>
中 移动 值,因为这比复制它们更便宜。或者甚至 交换 它们,让调用者决定是否销毁剩余的对象。 - sbi来自C++标准库:教程和参考资料
remove() - 通过用后面未被删除的元素覆盖它们来逻辑地删除具有给定值的元素。不会改变它们所操作的范围中的元素数量。相反,它们返回范围的新“结尾”的位置。
partition() - 更改元素的顺序,使满足条件的元素位于前面
stable_partition() - 与partition()相同,但保留匹配和非匹配元素的相对顺序
partition - 根据特定的谓词(例如 std::vector 中的奇数和偶数)将容器的元素“分组”
remove - 从容器中删除某个值;实际上,元素被移动到初始容器的末尾,返回一个指向新末尾的迭代器,并且“已删除”的元素仍然可以访问
编辑:
remove - 从容器中删除某个值;与上述所述不同,元素不会被移动到初始容器的末尾,而是返回一个指向新末尾的迭代器,但范围 [newEnd,last) 中的迭代器仍然可解引用,因此可访问,但它们指向的元素是未指定的。
remove_if
保持“好”的元素的相对顺序,而partition
可能会重新排列它们,因此partition
可以输出 4 2 5 1 3。如果好元素的相对顺序很重要,请使用stable_partition
,其输出保证是 2 4 1 3 5,保持每个组的相对顺序不变。 - Fabian