简体   繁体   English

表达式:使用 vector.erase() 时向量擦除迭代器超出范围

[英]Expression: vector erase iterator outside range when using vector.erase()

I am new to C++ and was trying to write a program that takes the lowest and the highest numbers in a vector, takes them away from the vector and proceeds to calculate an average with the rest of the numbers.我是 C++ 新手,并试图编写一个程序,该程序采用向量中的最低和最高数字,将它们从向量中取出并继续计算其余数字的平均值。

Now while I understand that I could do it after the numbers have been entered, I wanted to challenge myself and carry out these checks as the numbers were entered one by one.现在,虽然我知道我可以在输入数字后做到这一点,但我想挑战自己并在数字一个一个输入时进行这些检查。 I was looking around but I couldn't find another person with the exact issue I am having (since I am using vector.end() - 1).我环顾四周,但找不到与我遇到的确切问题有关的另一个人(因为我使用的是 vector.end() - 1)。

Below is my code and the error that it is giving me.下面是我的代码和它给我的错误。 Any guidance is much appreciated.非常感谢任何指导。

    #include <iostream>
    #include <iomanip>
    #include <vector>
    #include <algorithm>
    #include <numeric>
    #include <limits.h>
    
    using namespace std;
    typedef vector<int>::iterator iter;
    
    int main() {
    
        cout << "Please enter the series of scores: \n";
    
        // Read numbers from the standard input
        // and store them in a vector
        vector<int> scoreVector;
        int x = 0;
        int count = 0;
        // Assign the lowest possible value to the maximum possible integer so that any value entered initially will be lower that INT_MAX
        int lowestValue = INT_MAX;
        int highestValue = 0;
    
        iter lowestValueIndex;
        iter highestValueIndex;
    
        // Every time a number is entered, the program checks to see if it meets the criteria for the lowest or highest number entered so far
        while (cin >> x) {
    
            scoreVector.push_back(x);
    
            if (x > highestValue) {
                highestValueIndex = scoreVector.end() - 1;
                highestValue = x;
            }
            if (x < lowestValue) {
                lowestValueIndex = scoreVector.end() - 1;
                lowestValue = x;
            }
        }
    
        // Calculate the vector size
        auto n = scoreVector.size();
        
    
        if (n > 2) {
            
            cout << "\nThe lowest value is:" << lowestValue << "\nThe highest value is: " << highestValue << ". These values have been taken out." << '\n';
    
            // Remove the two values from the vector
            scoreVector.erase(lowestValueIndex);
            scoreVector.erase(highestValueIndex);
    
            // Calculate the average
            auto average = accumulate(scoreVector.begin(), scoreVector.end(), 0.0) / n;
    
            cout << "\naverage = " << average << '\n';
        }
        return 0;
    }

在此处输入图片说明

According to Iterator invalidation rules , scoreVector.push_back(x);根据迭代器失效规则scoreVector.push_back(x); may invalidate iterators taken before that by causing reallocation.可能会导致重新分配,从而使之前采用的迭代器无效。

You should save indice instead of iterators as indice.您应该将索引而不是迭代器保存为索引。

Also be careful because erase will shift following elements and it may affect indice of the element to be erased.还要小心,因为erase会移动后面的元素,它可能会影响要擦除的元素的索引。

Try this:尝试这个:

    #include <iostream>
    #include <iomanip>
    #include <vector>
    #include <algorithm>
    #include <numeric>
    #include <limits.h>
    
    using namespace std;
    typedef vector<int>::iterator iter;
    
    int main() {
    
        cout << "Please enter the series of scores: \n";
    
        // Read numbers from the standard input
        // and store them in a vector
        vector<int> scoreVector;
        int x = 0;
        int count = 0;
        // Assign the lowest possible value to the maximum possible integer so that any value entered initially will be lower that INT_MAX
        int lowestValue = INT_MAX;
        int highestValue = 0;
    
        size_t lowestValueIndex = 0;
        size_t highestValueIndex = 0;
    
        // Every time a number is entered, the program checks to see if it meets the criteria for the lowest or highest number entered so far
        while (cin >> x) {
    
            scoreVector.push_back(x);
    
            if (x > highestValue) {
                highestValueIndex = scoreVector.size() - 1;
                highestValue = x;
            }
            if (x < lowestValue) {
                lowestValueIndex = scoreVector.size() - 1;
                lowestValue = x;
            }
        }
    
        // Calculate the vector size
        auto n = scoreVector.size();
        
    
        if (n > 2) {
            
            cout << "\nThe lowest value is:" << lowestValue << "\nThe highest value is: " << highestValue << ". These values have been taken out." << '\n';
    
            // Remove the two values from the vector
            scoreVector.erase(std::next(scoreVector.begin(), lowestValueIndex));
            if (lowestValueIndex < highestValueIndex) highestValueIndex--;
            scoreVector.erase(std::next(scoreVector.begin(), highestValueIndex));
    
            // Calculate the average
            auto average = accumulate(scoreVector.begin(), scoreVector.end(), 0.0) / n;
    
            cout << "\naverage = " << average << '\n';
        }
        return 0;
    }

Inside your while loop, you are taking iterators to scoreVector .while循环中,您将迭代器带到scoreVector However, every time you do a push_back on a vector , all iterators to it are invalidated.但是,每次对vector执行push_back时,它的所有迭代器都会失效。 This means that when you exit your while loop, at least one if not both iterators are dangling.这意味着当您退出while循环时,如果不是两个迭代器,则至少有一个是悬空的。 Passing those iterators to .erase then invokes undefined behavior.将这些迭代器传递给.erase然后调用未定义的行为。

Instead, you should separate out the reading of the variables, and computation of the iterators that you want to erase:相反,您应该将变量的读取和要擦除的迭代器的计算分开:

while (cin >> x) { 
    scoreVector.push_back(x);
}

iter lowestValueIndex = std::min_element(scoreVector.begin(), scoreVector.end());
scoreVector.erase(lowestValueIndex);

iter highestValueIndex = std::max_element(scoreVector.begin(), scoreVector.end());
scoreVector.erase(highestValueIndex);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM