C ++集 - 联合,差异,相交 - 导致向量擦除迭代器错误(超出范围)

时间:2015-12-03 21:31:36

标签: c++ vector iterator set

好吧,我一直在撞墙。有时当代码运行时,我遇到错误“Expression:vector erase iterator outside range”。这是一个间歇性的问题。假设它与随机生成到向量中的数字有关。要获得错误,代码可能必须运行多次。

#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
#include <ctime>

using namespace std;

template <class T> class set
{
public:
    void add(T newElement);
    void remove(set<T> newElement, int pos);
friend set<T> operator-(set<T> set1, const set<T> set2){
    set<T> result;
    result = set1;
    for (int i = 0; i < set1.setVec.size(); i++){
        for (int j = 0; j < set2.setVec.size(); j++){
            if (set1.setVec[i] == set2.setVec[j]){
                result.remove(set1, i);
            }
        }
    }

    return result;
}
friend set<T> operator&(const set<T>& set1, const set<T> set2){
    set<T> result;
    for (int i = 0; i < set1.setVec.size(); i++){
        for (int j = 0; j < set2.setVec.size(); j++){
            if (set1.setVec[i] == set2.setVec[j]){
                result.add(set1.setVec[i]);
            }
        }
    }
    return result;
}
friend set<T> operator|(const set<T>& set1, const set<T> set2){
    set<T> result;
    result = set1;
    for (int i = 0; i < set2.setVec.size(); i++){
        result.add(set2.setVec[i]);
    }
    return result;
}
friend ostream& operator<< (ostream &output, const set<T> setOut){
    output << endl;
    for (int i = 0; i < setOut.setVec.size(); i++){

        output << setOut.setVec[i] << endl;
    }
    return output;
}
private:
    vector<T> setVec;
};
template <class T> 
void set<T>::add(T newElement){
    setVec.push_back(newElement);
}
template <class T>
void set<T>::remove(set<T> newElement, int pos){
    vector<T>::iterator it;
    it = setVec.begin();
    this->setVec.erase(it+3);
}
int main(){

    srand(time(NULL));

    cout << "=====INTEGERS=====" << endl;
    set<int> s;
    s.add(rand() % 10 + 1);
    s.add(rand() % 10 + 1);
    s.add(rand() % 10 + 1);
    s.add(rand() % 10 + 1);
    s.add(rand() % 10 + 1);
    s.add(rand() % 10 + 1);
    cout << "Set 1: " << s << endl;

    set<int> s2;
    s2.add(rand() % 10 + 1);
    s2.add(rand() % 10 + 1);
    s2.add(rand() % 10 + 1);
    s2.add(rand() % 10 + 1);
    s2.add(rand() % 10 + 1);
    s2.add(rand() % 10 + 1);
    cout << "Set 2: " << s2 << endl;

    set<int> s3;    
    s3 = s | s2;
    cout << "Set 1 Union Set 2: " << s3 << endl;
    s3 = s & s2;
    cout << "Set 1 Intersect Set 2: " << s3 << endl;
    s3 = s - s2;
    cout << "Set 1 Difference Set 2: " << s3 << endl;

    system("PAUSE");
    return 0;
}

基本上,我只是尝试在c ++中为模板化类重新创建集合符号。我已经在这约6个小时。任何帮助将不胜感激。

1 个答案:

答案 0 :(得分:2)

您的remove看起来错了:

template <class T>
void set<T>::remove(set<T> newElement, int pos){
    vector<T>::iterator it;
    it = setVec.begin();
    this->setVec.erase(it+3); // <--------------- maybe (it+pos) ??
}

在删除元素时,您必须注意在删除元素时大小会发生变化,即:

friend set<T> operator-(set<T> set1, const set<T> set2){
    set<T> result;
    result = set1;                           // here result.size == set1.size
    for (int i = 0; i < set1.setVec.size(); i++){
        for (int j = 0; j < set2.setVec.size(); j++){
            if (set1.setVec[i] == set2.setVec[j]){
                result.remove(set1, i);     // now result.size is smaller
            }
        }
    }
    return result;
}

使用迭代器可能更容易。类似的东西:

friend set<T> operator-(set<T> set1, const set<T> set2){
    set<T> result;
    result = set1;
    for (auto result::iterator it = result.first();it != result.end();/*empty*/){
        if (hasToBeRemoved(it)){
            result.remove();
        } else {
            ++it;
        }
    }

你也可以在没有迭代器的情况下做同样的事情,但你必须考虑,如果你在第3位搜索元素,那么下一个元素实际上是在第3位(而不是4)。