4

シンプルなConnect4ゲームをデザインしています。これまでのところ、4つの基礎となるクラスがあります。

Colour-色(RGBA)の表現を担当します。変換演算子が含まれています。

Player-ゲームのプレーヤーを表します。それぞれPlayerColourと名前があります。

Board-プレイボードを表します。Tileこれには、次元と、それらの次元を持つsの2Dベクトルが含まれています。

Tile-内のネストされたクラスBoard。ボード上の1つのスペースを表します。それぞれTileに、そのタイルの所有者に対するとがありますColourstd::unique_ptr所有者はとして開始し、一度からnullptrに変更できます。色は透明な黒から始まります。Player


Colourクラスをテストしましたが、正常に機能しているようです。私Playerのクラスも最高の形をしています。ただし、Board/Tileクラスに問題があります。

私のテストは、2人のプレーヤーと1つのボードを作成することで構成されました。これらは正常に実行されました。次に、タイルごとに1回、ボードの寸法をループします。それから私は電話します

board.tile (j, i).claimBy (p2); 

ループは、印刷されると予想される方法で、 行iと列を通過します。j

tile (j, i)作業中のタイルを取得します。期待どおりに動作します。


クラッシュにつながる一連のイベント:

claimBy (p2)プレイヤー2が要求するようにタイルを設定します。これは次のように実装されます。

bool Board::Tile::claimBy (const Player &owner)
{
    if (!_owner)
    {
        *_owner = owner;
        _colour = owner.colour();
        return true;
    }

    return false;
}

_owner私のstd::unique_ptr<Player>です。最初に、タイルの所有者が以前に設定されているかどうか(つまり、設定されていないかnullptr)を確認します。そうでない場合は、Player内部を渡されたものに設定します。次に、タイルの色を更新して、を返しますtrue。タイルが以前に要求されている場合は、を返しますfalse

デバッガーに続いて、クラッシュが行で発生します*_owner = owner;。ステップインすると、その行struct Player(クラスの宣言)に移動します。これは、暗黙のコピーコンストラクターであると見なされます(クラスにはaとaPlayerしかないことを思い出してください)。Colour _colourstd::string _name

もう一度ステップインすると、Colour::operator=(コピーコンストラクターが呼び出すのは理にかなっています)につながります。定義は次のとおりです。

Colour &Colour::operator= (const Colour &rhs)
{
    if (*this != rhs)
    {
        _red = rhs.red();
        _green = rhs.green();
        _blue = rhs.blue();
        _alpha = rhs.alpha();
    }

    return *this;
}

パスはに変わります*this != rhs。これは、の逆呼び出しoperator==です。つまり、次のようになります。

return red() == rhs.red()
    && green() == rhs.green()
    && blue() == rhs.blue()
    && alpha() == rhs.alpha();

ここでの最初の比較red() == rhs.red()red()、これだけreturn _red;です。これは、プログラムがクラッシュするポイントです。デバッガーは、thisthis->_red)が0x0であると述べています。

なぜこれが起こっているのか私にはわかりません。私の最善の推測は、私がスマートポインタを間違って使用しているということです。release私はこれまで実際に使用したことはありませんが、通常のポインターとかなり似ているはずであり、ポインターがである場合は何も達成できないと思いましたnullptr

this0x0になる原因は何でしょうか?

編集:
各コンストラクター、メンバー初期化子(例Board::Tile::Tile() : _colour (Colours::NONE), _owner (nullptr){})ですべてが初期化されていると確信しています。ここで、NONEは透明な黒です。

また、デバッグ値の出力にあまり使用していないため、デバッガーについてはあまり熟練していません。

4

2 に答える 2

3

この線

*_owner = owner;

owner「オブジェクトのコピーを作成し、それを_owner指す場所に保存する」という意味です。問題は、_ownerまだ何も指していないということです。それはまだnullです。

プレイヤーがコントロールする各タイルにオブジェクトのコピーを本当に作成したい場合は、次のことを行う必要があります。Player

_owner.reset(new Player(owner));

しかし、オブジェクトのコピーを作成するのPlayerは奇妙なことです。代わりに使用することを検討してくださいshared_ptr—両方を持つことができowner_owner通常shared_ptrの方法で一方を他方に割り当てることができます。

于 2012-04-26T01:59:52.017 に答える
1

デフォルトで初期化されたものから始めますstd::unique_ptr<Player>。つまり、いくつかのクリーンアップセマンティクスを持つNULLポインターに相当します。次に、ステートメントでそれを逆参照して、*_owner=owner;割り当てることができるようにします。

したがって、このステートメント*_owner=owner;は基本的に((Player*)NULL)->operator=(owner);、暗黙の代入演算子を呼び出すことと同じです。((Player*)NULL)->_colour=owner._colour; これが最初に行うことは、 Findingと同等this==NULLです。ここでは驚くことではありません。確かに、それは期待されています。

修正は、実際に何をしたいかによって異なります。それぞれBoard::Tileにその完全に新しいコピーを与える必要がありownerますか?次に、代わりに言いたい_owner.reset(new Player(owner))。各タイルに既存のプレーヤーへの参照を保持させたいだけですか?ownerPlayerオブジェクトがBoard::Tileオブジェクトよりも長持ちすることを保証できますか?次に、生のポインタが必要です:( Board :: Tileの宣言で)Player const *_owner;(実装で)_owner=&owner;

于 2012-04-26T02:12:06.600 に答える