1

这是我的 addCard 函数,它以 playCard 作为参数,然后将其自身的地址传递给分配的指向 playCard 对象的指针数组。

void cardHand::addCard(playingCard card) {
    theHand[nElems++] = &card;
} // addCard()

现在,当我运行我的程序时,它运行良好,但在调用析构函数时崩溃。

cardHand::~cardHand() {
    for(int c = 0;c<MAX;c++) {
        if(theHand[c] != NULL)
            delete theHand[c]; // here is the problem
    }
    delete [] theHand;
} // class destructor

是不是因为我只在 addCard 函数中交出了playingCard 对象的地址而崩溃了。它应该是一个指针吗?

4

7 回答 7

7

问题就在这里

void cardHand::addCard(playingCard card) { theHand[nElems++] = &card; }

您存储将在 addCard 方法结束时销毁的临时卡对象的地址。

在您的析构函数中,您尝试再次删除它。

你有两个选择。

首先:使 addCard 只接受卡片配置并newaddCard方法中创建您的卡片。
第二:通过指针接受卡片,但是你的cardHand的析构函数不能负责卡片的删除。删除将执行创建所有卡片的 Deck 对象。

于 2009-07-04T09:29:38.687 回答
6

当你说:

theHand[nElems++] = &card;

您正在存储函数参数的地址,它实际上是一个局部变量。这总是一件坏事,并且在您尝试删除它时会导致崩溃。

你可能想要这样的东西:

theHand[nElems++] = new playingcCard( card );

但真正的解决方案是使用 playCard 的 std::vector 并完全取消动态分配。

于 2009-07-04T09:31:13.270 回答
4

您将 C++ 用作更好的 C,尽管这对于许多用途都很好,但它不是惯用的 C++。

您真正想要的是完全取消动态分配。一般来说,如果你正在编写 C++,你应该很少使用new,甚至更不要使用delete.

你的手应该这样声明:

std::vector< playingCard > hand;

新卡应该用这样的东西放在上面:

hand.push_back( card );

您应该会发现,通过使用 C++ 库的集合类(和 TR1 智能指针),您永远不需要使用newdelete-- 直到您开始编写自己的智能指针。

于 2009-07-04T09:47:02.893 回答
1

它崩溃了,delete因为它从未分配给new.

void cardHand::addCard(playingCard card) {
    theHand[nElems++] = &card;
} // addCard()

在这个函数调用中,您传递了一张扑克牌的临时副本并获取它的地址。除非您真的知道自己在做什么,否则存储临时地址是一个禁忌。

相反,将其更改为类似

/** @param card card to add. Takes ownership. */
void cardHand::addCard(playingCard *card) {
    theHand[nElems++] = card;
} // addCard()

并在调用代码中,传递一个playingCardnew playingCard.

它仍然存在对象所有权转移的问题,这是双重删除错误或内存泄漏的常见原因。使用代码注释明确地进行此类传输是一个好习惯。

于 2009-07-04T09:29:32.930 回答
1

因此,鉴于其他答案,我的做法是交出引用或指向 a 的指针playingCard

而关于 delete,一般规则是,你只有deletenew编辑的,即分配内存的人应该负责它的处置。当然,与任何规则一样,也有例外,但这种行为需要在接口的合同中很好地记录。

于 2009-07-04T09:34:37.270 回答
1

重击规则:仅删除您分配的内容(使用 new 或使用 memalloc)

因此,你的崩溃。

于 2009-07-04T09:38:05.487 回答
1

它不起作用的原因是您在cardHand::addCard.
所以编译器所做的就是在堆栈上构造一个类实例的临时副本。由于它在堆栈上,因此一旦函数返回
,它将自动清理。 您可以通过将实例作为指针传递来解决此问题。 但是,正如这篇文章中的其他人所说,建议不要使用您没有明确表示的内容。addCard
playingCard
deletenew

于 2009-07-04T09:44:03.943 回答