C++ 使用for循环擦除向量中的元素

C++ 使用for循环擦除向量中的元素,c++,for-loop,vector,segmentation-fault,erase,C++,For Loop,Vector,Segmentation Fault,Erase,如何使用for循环通过其索引从向量中删除元素?我得到一个向量超出范围的错误。我在下面有一个示例代码 vector<int> to_erase = {0, 1, 2}; vector<int> data = {3, 3, 3, 3}; for(int i = 0; i < to_erase.size(); i++) { data.erase(data.begin() + to_erase[i]); } vector to_erase={

如何使用for循环通过其索引从向量中删除元素?我得到一个向量超出范围的错误。我在下面有一个示例代码

 vector<int> to_erase = {0, 1, 2}; 
 vector<int> data     = {3, 3, 3, 3};

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

    data.erase(data.begin() + to_erase[i]);
 }
vector to_erase={0,1,2};
向量数据={3,3,3,3};
对于(int i=0;i

我认为这是因为我的向量的大小在每次迭代中都会减小,因此它无法访问索引2。

在迭代过程中删除元素集合是不安全的,而且可能代价高昂。我建议每个满足您的条件的元素在最后都与一个元素交换。(在结尾处,因为从结尾处擦除会更便宜。您可以跟踪从向量结尾处返回的量(基于交换次数),并打破循环的早期。现在,根据交换的元素数,您可以执行以下操作:

data.resize(data.size() - reverse_counter);
#include <iostream>
#include <vector>
#include <limits>
#include <algorithm>
using namespace std;

int main() {

    vector<int> to_erase = {0, 1, 2}; 
    vector<int> data     = {3, 3, 3, 3};

    cout << "Before:\n" ;
    for(int i=0; i<data.size(); i++)
        cout << i << "\t";
    cout << endl;   
    for(int i=0; i<data.size(); i++)
        cout << data[i] << "\t";
    cout << endl;

    for(int i = 0; i < to_erase.size(); i++) {
        //data.erase(data.begin() + to_erase[i]);
        data[i] = numeric_limits<int>::max();
    }

    data.erase(remove_if(data.begin(), 
                         data.end(), 
                         [](int i){return i==numeric_limits<int>::max();}), data.end());

    cout << "Next:\n" ;
    for(int i=0; i<data.size(); i++)
        cout << i << "\t";
    cout << endl;
    for(int i=0; i<data.size(); i++)
        cout << data[i] << "\t";

    return 0;
}

这是sudo代码,只是为了解释这个想法

正如参考文献中所提到的,删除不是最终原因重新分配,这很昂贵。值得记住的是:

我想这是因为我的向量在每次迭代中都会减小

对!

您可以通过保留一个额外的变量来完成此操作,该变量对删除的元素进行计数,如下所示:

#include <iostream>
#include <vector>

using namespace std;

int main() {
        vector<int> to_erase = {0, 1, 2}; 
        vector<int> data     = {3, 3, 3, 3};

        int count_removed = 0;
        for(unsigned int i = 0; i < to_erase.size(); i++)
                data.erase(data.begin() + to_erase[i] - count_removed++);

        for(unsigned int i = 0; i < data.size(); ++i)
                        cout << data[i] << "\n";
        return 0;
}
data.erase(remove_algorithm(begin(data), end(data)), end(data));
#包括
#包括
使用名称空间std;
int main(){
要擦除的向量={0,1,2};
向量数据={3,3,3,3};
int count_removed=0;
for(无符号整数i=0;icout我认为这是一个糟糕的设计,因为您将更改for循环不变量,并且需要大量的解决方法来实现这一点。无论如何,如果您确实想使用for循环,您可以标记要删除的内容并运行stl remove\u,如:

data.resize(data.size() - reverse_counter);
#include <iostream>
#include <vector>
#include <limits>
#include <algorithm>
using namespace std;

int main() {

    vector<int> to_erase = {0, 1, 2}; 
    vector<int> data     = {3, 3, 3, 3};

    cout << "Before:\n" ;
    for(int i=0; i<data.size(); i++)
        cout << i << "\t";
    cout << endl;   
    for(int i=0; i<data.size(); i++)
        cout << data[i] << "\t";
    cout << endl;

    for(int i = 0; i < to_erase.size(); i++) {
        //data.erase(data.begin() + to_erase[i]);
        data[i] = numeric_limits<int>::max();
    }

    data.erase(remove_if(data.begin(), 
                         data.end(), 
                         [](int i){return i==numeric_limits<int>::max();}), data.end());

    cout << "Next:\n" ;
    for(int i=0; i<data.size(); i++)
        cout << i << "\t";
    cout << endl;
    for(int i=0; i<data.size(); i++)
        cout << data[i] << "\t";

    return 0;
}
#包括
#包括
#包括
#包括
使用名称空间std;
int main(){
要擦除的向量={0,1,2};
向量数据={3,3,3,3};

cout通常情况下,您会使用从向量中高效地删除多个元素(逐个删除它们通常效率较低,而且正如您所看到的,并不总是微不足道的)。在最一般的形式中,该习语如下所示:

#include <iostream>
#include <vector>

using namespace std;

int main() {
        vector<int> to_erase = {0, 1, 2}; 
        vector<int> data     = {3, 3, 3, 3};

        int count_removed = 0;
        for(unsigned int i = 0; i < to_erase.size(); i++)
                data.erase(data.begin() + to_erase[i] - count_removed++);

        for(unsigned int i = 0; i < data.size(); ++i)
                        cout << data[i] << "\n";
        return 0;
}
data.erase(remove_algorithm(begin(data), end(data)), end(data));
在您的例子中,
remove\u算法
基于另一个向量中的索引,因此我们也需要提供这些索引:

data.erase(
    remove_indices(begin(data), end(data), begin(to_erase), end(to_erase)),
    end(data));
不幸的是,这样的算法不包含在标准库中。但是,编写您自己1是很简单的:

模板
自动删除索引(开始、结束、It2 idx_b、It2 idx_e)->It{
使用idx\u t=typename std::iterator\u traits::value\u type;
std::sort(idx_b,idx_e,std::greater{});
对于(;idx_b!=idx_e;++idx_b){
自动位置=开始+*idx_b;
标准::移动(标准::下一个(位置),结束--,位置);
}
返回端;
}
在这里,我们首先将要删除的索引从最大到最小进行排序。接下来,我们循环这些索引。然后(最大效率地)将当前位置(要删除)和向量末尾之间的所有元素向前移动一个。随后,末尾减少一个(考虑到元素被删除的事实)



1*Ahem*删除代码中所有愚蠢的打字错误后。

也许您可以对索引数组进行排序,并从最后一个开始删除元素one@Marievi希望瑞琪也觉得有用。