仅在剩余条目的向量pop_back()崩溃

时间:2016-10-07 07:08:53

标签: c++ vector crash

代码:

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

struct myClass {
    bool bIsDead;
    myClass(bool bDead) {
        this->bIsDead = bDead;
    }
};

void PrintVector(std::vector<myClass*> vec) {
    std::cout << "The vector contains: ";
    for(int i = 0; i < vec.size(); i++) {
        std::cout << vec[i]->bIsDead << " ";
    }
    std::cout << std::endl;
}

int main() {

    std::srand(std::time(0)); // use current time as seed for rng

    std::vector<myClass*> myVector;
    for(int i = 0; i < 10; i++) {
        int tempRand = std::rand() % 2;
//      int tempRand = 1;
        if(tempRand == 1) {
            myVector.push_back(new myClass(true));
        }
        else {
            myVector.push_back(new myClass(false));
        }
    }

    std::cout << "Unsorted: " << std::endl;
    PrintVector(myVector);

    std::sort(myVector.begin(), myVector.end(), [ ]( const myClass *lhs, const myClass *rhs )
    {
        return lhs->bIsDead < rhs->bIsDead;
    });

    std::cout << "Sorted: " << std::endl;
    PrintVector(myVector);


    while(myVector.back()->bIsDead) {
        delete myVector.back();
        myVector.pop_back();
    }

    std::cout << "Removed Dead Ones: " << std::endl;
    PrintVector(myVector);

    return 0;
}

随机输入的输出:

Unsorted: 
The vector contains: 0 0 1 0 0 0 1 1 0 1 
Sorted: 
The vector contains: 0 0 0 0 0 0 1 1 1 1 
Removed Dead Ones: 
The vector contains: 0 0 0 0 0 0 

Hit ENTER to continue...

所有1的输出(即pop_back全部删除):

Unsorted: 
The vector contains: 1 1 1 1 1 1 1 1 1 1 
Sorted: 
The vector contains: 1 1 1 1 1 1 1 1 1 1 

Hit ENTER to continue...

对于这个控制台应用程序,我没有给出任何错误或崩溃警告,但是在pop_back调用所有1的情况之后它不会输出两个cout语句。

为什么将指针向量弹回到空的任何想法都会导致程序崩溃?

3 个答案:

答案 0 :(得分:0)

您需要添加一个矢量大小的检查。如果要使用back()访问向量的最后一个元素,则它不应为0。

改变这个:

while(myVector.back()->bIsDead) {

为:

while(myVector.size() > 0 && myVector.back()->bIsDead) {

这里有正确的代码:

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

struct myClass {
    bool bIsDead;
    myClass(bool bDead) {
        this->bIsDead = bDead;
    }
};

void PrintVector(std::vector<myClass*> vec) {
    std::cout << "The vector contains: ";
    for(int i = 0; i < vec.size(); i++) {
        std::cout << vec[i]->bIsDead << " ";
    }
    std::cout << std::endl;
}

int main() {

    std::srand(std::time(0)); // use current time as seed for rng

    std::vector<myClass*> myVector;
    for(int i = 0; i < 10; i++) {
        int tempRand = std::rand() % 2;
//      int tempRand = 1;
        if(tempRand == 1) {
            myVector.push_back(new myClass(true));
        }
        else {
            myVector.push_back(new myClass(false));
        }
    }

    std::cout << "Unsorted: " << std::endl;
    PrintVector(myVector);

    std::sort(myVector.begin(), myVector.end(), [ ]( const myClass *lhs, const myClass *rhs )
    {
        return lhs->bIsDead < rhs->bIsDead;
    });

    std::cout << "Sorted: " << std::endl;
    PrintVector(myVector);


    while(myVector.size() > 0 && myVector.back()->bIsDead) {
        delete myVector.back();
        myVector.pop_back();
    }

    std::cout << "Removed Dead Ones: " << std::endl;
    PrintVector(myVector);

    return 0;
}

引用cppreference

  

在空容器上调用此函数(back())会导致未定义   行为。

PS:你不需要让这个问题看起来如此令人生畏,引起我们的注意。

答案 1 :(得分:0)

与我遇到的大多数问题一样,这很简单。感谢billz和juanchopanza的评论,有人向我指出,pop_back()并没有崩溃,而是在while循环中调用的后续back()

这可以通过多种方式轻松解决,例如: 将if(myVector.empty) {break;}添加到删除的while循环中 或者像user3286661所说的那样,在while循环中添加一个条件,首先检查它是否有一个元素。

答案 2 :(得分:0)

问题是,即使向量已经为空,您也会尝试访问myVector.back()

最少侵入性的解决方案(对代码的最小修改)我能想到的是:

while (!myVector.empty() && myVector.back()->bIsDead) {
    delete myVector.back();
    myVector.pop_back();
}

“正确”的做法是使用std::vector<myClass>std::vector<std::unique_ptr<myClass>>(无需手动删除)并使用erase-remove-idiom

myVector.erase(
    std::remove_if(myVector.begin(), myVector.end(), 
        [](const auto& p) {
            return p->bIsDead; //p.bIsDead for std::vector<myClass>
        }
    ), 
    myVector.end()
);

这可能看起来更复杂,但它更安全(没有意外的内存泄漏),可能效率更高,而则不需要调用sort