0

我想删除值大于 2 且小于 5 的所有元素,代码如下:

 vector<int> myvector{3, 3, 3, 3, 3, 3, 3, 1, 2, 3, 4, 5 , 2, 3, 4, 9};
 vector<int>::iterator it;

 it = myvector.begin();
 for(int i = 0; i < myvector.size(); i++)
 {
   if(myvector[i] > 2 && myvector[i] < 5)
   {
     myvector.erase(it+i);
   }
     
 }
 for(int i = 0; i < myvector.size(); i++)
 {
   cout << ' ' << myvector[i];
     
 }

输出:3 3 3 1 2 4 5 2 4 9

问题出在哪里。

4

2 回答 2

3

使用应用标准算法 std::remove_if 的方法。例如

#include <vector>
#include <iterator>
#include <algorithm>

//...

    std::vector<int> myvector{ 3, 3, 3, 3, 3, 3, 3, 1, 2, 3, 4, 5 , 2, 3, 4, 9 };

    myvector.erase( std::remove_if( std::begin( myvector ), std::end( myvector ),
        []( const auto &item )
        {
            return 2 < item && item < 5;
        } ), std::end( myvector ) );

    for (const auto &item : myvector) std::cout << item << ' ';
    std::cout << '\n';

此代码段的输出是

1 2 5 2 9

使用这个 for 循环

for(int i = 0; i < myvector.size(); i++)

是不正确的。例如,如果您有一个包含 2 个元素的向量,并且在第一次迭代中,当 i 递增并等于 1 时,索引为 0 的元素被删除。所以现在 i 等于 1 不小于然后返回的size()值第二个元素不会被删除。

除此之外,这种在向量中顺序擦除元素的方法也是低效的。

于 2020-12-08T09:10:20.873 回答
1

erase问题在于在循环中使用该函数与该修改的迭代器vector。从函数的cppreference 页面erase(粗体我的):

从容器中擦除指定的元素。

  1. 移除 pos 处的元素。
  2. 删除范围 [first, last) 中的元素。

在擦除点处或之后使迭代器和引用无效,包括 end() 迭代器。

可以正确擦除循环内的元素,但这有点棘手。更简单的方法是应用erase-remove-idiom。或者,如果您可以使用 C++20,请查看std::erase_if.

于 2020-12-08T09:02:39.213 回答