5

我正在编写一个程序,我想在其中画一张卡片,然后删除它,这样它就不会再次被画出来。

我有一个卡片向量(包含定义 Suit 和 Value 的 2 个结构的类),称为deck,我真的不知道如何很好地使用迭代器,这里有一个代码片段:

void Player::discardCard(CardDeck masterDeck)
{
    cout << "Erasing: " << masterDeck.getDeck().at(cardSelect).toString() << endl;
    /*Attempt1*/
    masterDeck.getDeck().erase(masterDeck.getDeck().begin()+cardSelect);

    /*Attempt 2*/
    vector<Card>::iterator itr;
    itr = masterDeck.getDeck().begin() + cardSelect;
    masterDeck.getDeck().erase(itr);
}

cardSelect 有我要删除的卡片的位置。它是在0和deck大小的边界内随机生成的;因此它不应该指向一个超出边界的位置。

每次编译时都会出现以下错误:

"Expression: vector erase iterator outside range"

我真的不知道该怎么办,希望有人能帮助我,提前谢谢!

4

3 回答 3

1

我敢打赌,它getDeck按值返回向量。它导致itr指向erase向量的不同副本并对其进行操作。因此你得到错误。您应该通过引用返回向量。将签名更改getDeck为此:

vector<Card>& getDeck()
于 2011-04-01T06:08:58.253 回答
1

让我先跑题。你的设计有点可疑。首先按值传入 CardDeck 几乎可以肯定不是您想要的,但这甚至是无关紧要的。为什么你的 Player 类应该对 CardDeck 的私有内部有所有这些内部知识。它不应该关心你将甲板存储为向量或双端队列(哈哈),或者结构是什么。它只是不应该知道这一点。它所知道的只是它想要丢弃一张牌。

masterDeck.Discard(selectedCard);

还要注意 selectedCard 必须在 0 到1 之间,比牌组的大小少,但即使这样也可能不是你的问题(尽管它会是 1/53 的时间

所以要回答你的问题,我们现在真的需要更多关于 masterDeck 的知识。您是否实现了有效的自定义复制构造函数?由于您按价值传递的可能性很好,因此您没有正确复制基础向量,实际上它可能是空的,并且任何删除都不会起作用。尝试检查大小。如果您不想复制套牌,那么您可以让编译器通过声明私有复制构造函数然后从不定义它来帮助您。请参阅 Scott Meyer 的 Effective C++ Item 11。

最后一条建议,我相信一旦你用你的迭代器擦除,你就会使它无效。向量可能会被重新分配(如果你擦除除了结尾之外的任何地方,几乎肯定会重新分配)。我只是告诉你,这样你就不会尝试在同一个迭代器上多次调用 erase。关于迭代器的一个棘手的事情是使它们无效是多么容易,这就是为什么你经常看到检查 iter != coll.end() 的原因。

于 2011-04-01T06:01:09.540 回答
0

“它是在 0 和甲板大小的边界内随机生成的”。

有效范围应该是“介于 0 和牌组大小减 1 之间”。这可能会在运行时产生范围错误。

于 2011-04-01T06:05:29.267 回答