谁能解释一下为什么这个代码不能从向量上擦除所有的15:
for (int i = 0; i < numbers.size(); i++)
{
if (numbers[i] == 1)
{
numbers.erase(numbers.begin() + i);
}
}
让我们试一试。
假设你有一个内容为[1, 1, 1]
的向量(所有的,为了简单)
第一次迭代:
for (int i = 0; i < numbers.size(); i++) <-- i == 0; numbers.size() == 3
{
if (numbers[i] == 1) <-- true
{
numbers.erase(numbers.begin() + i); <-- erase is called on element #0
}
}
第二个迭代:向量现在包含了[1, 1]
,因为我们移除了第0个元素。
for (int i = 0; i < numbers.size(); i++) <-- i == 1; numbers.size() == 2
{
if (numbers[i] == 1) <-- true
{
numbers.erase(numbers.begin() + i); <-- erase is called on element #1
}
}
第三个迭代:向量现在包含[1]
for (int i = 0; i < numbers.size(); i++) <-- i == 2; numbers.size() == 1; the loop condition is false, so we exit the loop
{
if (numbers[i] == 1)
{
numbers.erase(numbers.begin() + i);
}
}
最终结果:
向量包含[1]
正如您可能从手动逐行计算代码中看到的那样,问题是即使在删除元素之后也增加了i
。每次你移除一个元素,你把所有剩下的元素移到下标,但同时,你增加计数器,所以你看到的下一个索引是高一个。因此,当您删除元素i
时,先前索引为i+1
的元素被移动到索引i
。但是在下一次迭代中,您不再查看索引i
,而是查看索引i+1
,因此您跳过了一个元素,而没有查看它。
您的代码显示我& lt;numbers。size(),你增加I同时删除n[I](如果它是1)删除后,不应该增加i,因为新数字会进入i的当前位置。
如果数字[]= {0、1、2、3、1、4}>你得到数字[]= {0、2、3、4}
如果数字[]= {0、1、1、2、3、1、4}>你得到数字[]= {0 1 2 3 4} ,
。E删除后,跳过下一个数字只要加上i——;删除数字后[i]
for (int i = 0; i < numbers.size(); i++){
if (numbers[i] == 1){
numbers.erase(numbers.begin() + i);
i--;
}
}
这将给你正确的答案。
当vector对象的一个元素被删除时,该元素之后的所有元素都向左移动。例如,如果索引为0的元素被删除,那么向量的第一个实际元素的索引将等于9。在这种情况下,您不能增加索引。
有效的循环可以像
for ( int i = 0; i < numbers.size(); )
{
if ( numbers[i] == 1 )
{
numbers.erase( numbers.begin() + i );
}
else
{
++i;
}
}
考虑到应用标头<algorithm>
std::remove
更简单例如#include <algorithm>
//...
numbers.erase( std::remove( numbers.begin(), numbers.end(), 1 ), numbers.end() );
下面是一个示范示例
#include <iostream>
#include <vector>
#include <algorithm>
int main()
{
std::vector<int> v = { 1, 1, 2, 1, 3, 1, 4, 1, 5 };
for ( int x : v ) std::cout << x << ' ';
std::cout << std::endl;
v.erase( std::remove( v.begin(), v.end(), 1 ), v.end() );
for ( int x : v ) std::cout << x << ' ';
std::cout << std::endl;
return 0;
}
输出为
1 1 2 1 3 1 4 1 5
2 3 4 5