为何在std::remove中直接传ar[0]而非x会得到不同结果?
为什么用
ar[0]代替变量x传入std::remove会得到不同结果? 首先先看你的代码片段(已格式化):
#include <iostream> #include <vector> #include <set> #include <algorithm> using namespace std; int main() { vector<int> ar = {1, 2, 2, 2, 3, 4, 5, 5, 5, 6, 7}; vector<int> sum; int n = ar.size(); for (int i = 0; i < n; i++) { int x = ar[0]; int frq = count(ar.begin(), ar.end(), x); int q = frq / 2; sum.push_back(q); ar.erase(remove(ar.begin(), ar.end(), x), ar.end()); // 此处用x结果正确 // 若替换为 ar.erase(remove(ar.begin(), ar.end(), ar[0]), ar.end()); 结果出错 } int count = 0; int n1 = sum.size(); for (int i = 0; i < n1; i++) { count = count + sum[i]; } cout << count; }
核心原因:std::remove执行过程中会修改ar[0]的值!
你可能觉得ar[0]和x是同一个值,传入哪个都一样,但本质上两者有天差地别:
- 当你用
x时,x是提前拷贝的ar[0]初始值(比如第一次循环时是1),这个值在整个remove执行过程中是固定不变的。std::remove会精准标记所有等于1的元素,最后erase删掉它们,完全符合预期。 - 但直接传
ar[0]就不一样了:std::remove的工作逻辑是把不等于目标值的元素往前移动,在这个过程中,ar[0]的位置会被后面的元素覆盖!比如第一次循环时,ar[0]一开始是1,但remove遍历到第一个2的时候,会把2赋值到当前的「待填充」位置(也就是ar.begin(),即ar[0]),这时候ar[0]就变成2了!
接下来,remove后续的比较都会用**新的ar[0]的值(也就是2)**来判断,而不是原来的1。这就导致它不会再把剩下的1标记为要删除的元素,最终erase之后,vector里的逻辑彻底混乱,结果自然不对。
直观的第一次循环对比:
初始ar:[1,2,2,2,3,...]
- 用
x=1传remove:所有等于1的元素被标记,erase后ar变成[2,2,2,3,...],符合预期。 - 用
ar[0]传remove:- 初始
ar[0]是1,remove寻找不等于1的元素。 - 第一个找到的2被赋值到
ar[0],此时ar变成[2,2,2,2,3,...]。 - 后续
remove会用新的ar[0]值(2)来判断,只把3、4等非2元素往前移,erase后ar变成[2,2,2,3,4,...],原来的1被覆盖消失,但剩余的2未被正确处理,后续循环逻辑完全偏离。
- 初始
简单来说,ar[0]在remove执行过程中是动态变化的,而x是固定的副本,这就是两者结果不同的关键。
内容的提问来源于stack exchange,提问作者saurov deb
相关产品推荐
相关产品推荐

