【问题标题】:C++ Sets - Union, Difference, Intersect - Causing vector erase iterator error (Outside of range)C++ 集 - 并集、差异、相交 - 导致向量擦除迭代器错误(超出范围)
【发布时间】:2015-12-03 21:31:35
【问题描述】:

好吧,我一直在敲墙。有时在运行代码时,我会遇到错误“表达式:向量擦除迭代器超出范围”。这是一个间歇性问题。假设它与随机生成到向量中的数字有关。要获得错误,代码可能必须运行多次。

#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 个小时。任何帮助将不胜感激。

【问题讨论】:

  • 我相信这个this-&gt;setVec.erase(it+3); 应该是this-&gt;setVec.erase(it+pos);... 看起来像是一个错字:)
  • 已更改,但我认为这不是问题的全部。事情我做得太久了。大声笑。
  • 不要在你的问题中改变它!!!这使您的问题(和答案)对未来的读者几乎毫无用处
  • 老实说,这个问题是否会对任何未来的读者有所帮助是值得怀疑的;)但除了讽刺之外,您不应该在自己的问题中解决您所要求的问题!如果您找到了修复,您可以将其发布为答案,如果已经有修复的答案,您可以接受这个。
  • 对不起!没有考虑到这一点。谢谢。

标签: c++ vector iterator set


【解决方案1】:

您的 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)。

【讨论】:

  • ps:错误信息其实很清楚,也许你只是需要休息一下;)
  • 是的,我可能会!哈哈。我正在尝试一些东西,但由于某种原因,即使进行了更正,它也会给我同样的错误。
猜你喜欢
  • 1970-01-01
  • 2018-01-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-01-24
  • 1970-01-01
  • 1970-01-01
  • 2018-04-16
相关资源
最近更新 更多