题
这是我的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的析构函数不能负责卡删除。和删除将执行其创建所有的卡片甲板对象。
其他提示
当你说:
theHand[nElems++] = &card;
您正在存储的功能参数,从而有效地是一个局部变量的地址。这始终是一个坏的事情,和你的情况导致崩溃当您尝试将其删除。
您可能想是这样的:
theHand[nElems++] = new playingcCard( card );
但真正的解决方案是使用游戏牌的一个std ::向量和到完全脱离动态分配。
您是使用C ++作为一种更好的C,虽然这是罚款,许多用途是不地道的C ++。
你真正想要的是干脆废除动态分配。一般来说,如果你正在写C ++,你应该很少使用new
更很少使用delete
。
您的手应该声明是这样的:
std::vector< playingCard > hand;
新卡应放在它是这样的:
hand.push_back( card );
您会发现,通过使用C ++库的集合类(和TR1智能pointes的),你永远不会需要使用new
或delete
- 直到你到达反正写你自己的智能指针
因此,考虑其他的答案,我做这将是交出引用或指针playingCard
的方式。
和与问候delete
,一般的规则是,你只delete
你new
ed什么,即谁分配内存应负责其disposale之一。
当然,如同任何规则,也有例外,但需要一个接口的合同中记载得非常好这一行为。
有崩溃上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
对象的指针。
它仍然有对象所有权转移的问题,其为双的一个常见原因删除错误或内存泄漏。这是一个好习惯,使这种转让明确与代码中的注释。
经验法则:只有删除你分配什么(或者与新的或使用malloc)
因此,你的崩溃。
它不工作的原因是,你传递你的类的价值由cardHand::addCard
。结果
那么编译器的作用是构造你的类实例的堆栈上的临时副本。结果
因为它是在栈上,它会被自动清除一次addCard
函数返回。结果
你可以通过你的playingCard
实例作为一个指针,而不是解决这个问题。结果
然而,正如其他人在这个岗位已经说过,这是最好不要delete
东西,你没有明确new
。