每当我调用dominoes.erase()类型的std::vector<Domino>时,都会遇到分段错误;即使我将值硬编码。

一个单独的成员函数调用dominoes.push_back()加载数据,并且我能够使用pop_back()从 vector 中删除并返回一个多米诺骨牌,所以我知道里面有数据。我已经在Domino对象上制作了一个复制构造函数,并且效果很好。我将其范围缩小到dominoes.erase()

Domino::Domino( const Domino &d ) {
    left = d.getHighPip();
    right = d.getLowPip();

}
Domino DominoCollection::drawDomino( void )
{

    int index = random.nextNumber( dominoes.size()  );
    Domino d( dominoes[index] );
    dominoes.erase( dominoes.begin() + index );

    return Domino( d );
}

任何帮助将不胜感激。谢谢!

最佳答案

尝试通过删除所有不必要的代码(对象复制, vector 访问...)来缩小错误的范围。然后,如果问题确实来自erase,请添加保护措施以确保索引正确。尝试使用以下代码:

#include <cassert>
void DominoCollection::drawDomino( void )
{
    assert(dominoes.size() != 0 && "Your vector is empty");
    int index = random.nextNumber( dominoes.size()  );
    assert(index < dominoes.size() && "Buffer overflow...");
    dominoes.erase( dominoes.begin() + index );
}

如果仍然存在段错误,则问题来自Domino类的析构函数。看看那里是否有鱼。您可以通过注释析构函数的一部分(或全部)来进行快速测试,以了解问题的根源。调用erase将调用Domino的析构函数。

如果未实现析构函数,则最好实现一个带有输出的析构函数(在cerr上,而不是cout上),以了解它是否到达那里或更早崩溃。 Domino是派生类吗?它是否包含其他任何对象或仅包含原始类型的组合?

编辑

我快速浏览了您的代码:问题来自赋值运算符:
Domino & Domino::operator = ( const Domino & d )
{
    *this = d;
}

这是而不是应该如何编写...我让您调试一下作为练习。

至于为什么这是错误的根源:您说erase崩溃了,但不是pop_back。两者之间的主要区别(实现上的区别,不是明显的语义上的区别)是,擦除会导致所有元素在删除后都发生移位(使用=运算符),因为std::vector要求元素要连续存储。而pop只会更改尾指针,而不会更改容器的其余部分。

关于c++ - 调用vector.erase()时出现段错误,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/16135874/

10-11 18:15