如何结合std::copy_if复制元素并从原容器移除已复制元素?
解决方案
你可以通过两种实用方式实现「移动偶数到新容器并从原容器移除」的需求,具体实现如下:
方法一:先移动元素,再用erase-remove_if清理原容器
基于你现有的代码,在完成元素移动后,直接用STL的erase-remove惯用法删除原容器中的偶数元素:
#include <vector> #include <algorithm> int main() { std::vector<int> v = {1, 2, 3, 4, 5, 6}; std::vector<int> even; // 移动偶数元素到even std::copy_if(std::make_move_iterator(v.begin()), std::make_move_iterator(v.end()), std::back_inserter(even), [](int i){return i%2 == 0;}); // 从v中移除所有偶数 v.erase(std::remove_if(v.begin(), v.end(), [](int i){return i%2 == 0;}), v.end()); return 0; }
注意:对于int这类简单类型,移动后原元素的值不会变化;如果是带资源的复杂类型(比如std::string),移动后的原元素处于有效但未定义状态,但remove_if的判断逻辑依然生效,因为只依赖值是否为偶数。
方法二:先分区再移动,减少遍历次数
这种方法先把原容器中的偶数元素移到容器末尾,再将这部分元素转移到even,最后截断原容器保留奇数元素。相比方法一,仅需两次遍历(分区+移动),效率更高:
#include <vector> #include <algorithm> int main() { std::vector<int> v = {1, 2, 3, 4, 5, 6}; std::vector<int> even; // 将偶数元素移动到容器末尾,返回第一个偶数元素的迭代器 auto even_start = std::partition(v.begin(), v.end(), [](int i){return i%2 != 0;}); // 移动末尾的偶数元素到even even.insert(even.end(), std::make_move_iterator(even_start), std::make_move_iterator(v.end())); // 截断原容器,移除已移动的偶数元素 v.erase(even_start, v.end()); return 0; }
如果需要保留原容器中奇数元素的相对顺序,可将std::partition替换为std::stable_partition,但后者时间复杂度会略高(O(n log n))。
内容的提问来源于stack exchange,提问作者ATK
相关产品推荐
相关产品推荐

