1

これは私の addCard 関数で、playingCard をパラメーターとして取り、それ自体のアドレスを、playingCard オブジェクトへのポインターの割り当てられた配列に渡します。

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 メソッドの最後で破棄される一時カード オブジェクトのアドレスを格納します。

そして、デストラクタでもう一度削除しようとします。

2 つのオプションがあります。

最初: addCard を作成して、カード構成のみを受け入れnewaddCardメソッドでカードを作成します。
2 番目: カードをポインタで受け入れますが、cardHand のデストラクタはカードの削除を担当できません。そして削除は全てのカードを作成したデッキオブジェクトを行います。

于 2009-07-04T09:29:38.687 に答える
6

あなたが言う時:

theHand[nElems++] = &card;

事実上ローカル変数である関数パラメーターのアドレスを格納しています。これは常に悪いことであり、あなたの場合、削除しようとするとクラッシュが発生します。

おそらく次のようなものが必要です。

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

しかし、本当の解決策は、playingCard の 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 スマート ポイント) を使用することで、独自のスマート ポインターを作成するまではnew、または-- を使用する必要がないことがわかります。delete

于 2009-07-04T09:47:02.893 に答える
1

deleteで割り当てられていないため、クラッシュしnewます。

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

この関数呼び出しでは、playingCard の一時的なコピーを渡し、そのアドレスを取得しています。自分が何をしているのかを本当に理解していない限り、一時的なアドレスを保存することはできません。

代わりに、それを次のように変更します

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

playingCard呼び出し元のコードでは、から返されたオブジェクト ポインターを渡しますnew playingCard

二重削除のバグやメモリリークの一般的な理由であるオブジェクト所有権の譲渡の問題がまだあります。このような転送をコード コメントで明示するのは良い習慣です。

于 2009-07-04T09:29:32.930 に答える
1

したがって、他の答えが与えられた場合、それを行う私の方法は、への参照またはポインターを渡すことになりますplayingCard

そして に関しては delete、一般的なルールは、あなたが編集しdeleteたものだけnew、つまりメモリを割り当てた人がその廃棄に責任を持つべきだということです。もちろん、他の規則と同様に、これには例外がありますが、この動作はインターフェイスの契約で十分に文書化する必要があります。

于 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 に答える