析构函数问题
这是我的addCard函数,它将一张纸牌作为参数,然后将其自身的地址移交给分配给扑克对象的指针数组。析构函数问题
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函数中移交了扑克对象的地址。它应该是一个指针吗?
的问题是在这里
void cardHand::addCard(playingCard card) { theHand[nElems++] = &card; }
您存储将在addCard方法结束时破坏的临时卡对象的地址。
而在你的析构函数中,你试图再次删除它。
您有两种选择。
第一个:使addCard接受只是卡配置和new
在addCard
方法创建您的卡。
秒:用指针接受卡,但是你的cardHand的析构函数不能负责删除卡。删除将执行创建所有卡片的Deck对象。
它在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()
而在调用代码,它传递一个playingCard
对象的指针从new playingCard
返回。
它仍然存在对象所有权转移的问题,这是双重删除错误或内存泄漏的常见原因。使用代码注释来显式传输这样的传输是一个好习惯。
当你说:
theHand[nElems++] = &card;
您存储函数参数,这实际上是一个局部变量的地址。这总是一件坏事,在你试图删除它的时候会导致崩溃。
你可能想是这样的:
theHand[nElems++] = new playingcCard(card);
但真正的解决方案是使用游戏牌的一个std ::载体,干脆弄死动态分配。
所以给出其他答案,我的做法是交出一个参考或指向playingCard
的指针。
而对于delete
,一般规则是,你只有delete
你new
编辑的内容,即分配内存的人应该对其处置负责。 当然,与任何规则一样,这也有例外,但这种行为需要在界面合同中记录得很好。
扑通的规则:只有删除你分配什么(或者与新的或memalloc)
因此,你的崩溃。
我喜欢“扑通”规则:-) – 2009-07-04 10:12:56
它不起作用的原因是你在cardHand::addCard
的价值传递你的课程。
因此,编译器会在栈上构造类实例的临时副本。
当它在堆栈上时,一旦addCard
函数返回,它将自动清除。
您可以通过将您的playingCard
实例作为指针来解决此问题。
但是,正如在这篇文章中的其他人所说,建议不要delete
东西,你没有明确new
。
您正在使用C++作为更好的C,虽然这对许多用途都很好,但它不是惯用的C++。
你真正想要的是完全消除动态分配。一般来说,如果你正在编写C++,你应该很少使用new
,甚至更少使用delete
。
你的手应该像这样声明:
std::vector<playingCard> hand;
新卡应放在它是这样的:
hand.push_back(card);
你会发现,通过使用C++库的集合类(和TR1智能指针),你永远不需要使用new
或delete
- 直到你开始写自己的智能指针。
我也建议将签名更改为void cardHand :: addCard(const playingCard&card) – Niklas 2009-07-04 09:56:11
查看下面有关使用局部变量去使用new&()用法的人们的回答......说了这么一句话,请确定您是否有相应的cardHand :: removeCard()方法,您将theHand [xyz ]删除(删除())到0时,否则您将尝试删除已删除的对象。如果非null真的意味着它仍然是一个有效的对象,那么在析构函数中的检查是有价值的。另外,我会将NULL更改为0 ... – Dan 2009-07-04 14:33:13