0

答えを見つけるために何を検索すればよいかわかりません。そのため、関連する記事にリダイレクトしてください。事前にお詫び申し上げます。

私は C++ が初めてで、3x3 CLI タイル ゲームを作成しようとしています。TileGame コンストラクターで Tile オブジェクトをポインターのプライベート配列に割り当て、それらが有効なメモリ アドレスを持っていることを確認できます (またはそう思う)。私の問題は、メソッドを実行してそのデータにアクセスしようとするときです。配列の最初の要素に値があるように見えますが、他の要素は非常に奇妙に見えます。些細なことだとは思いますが、何がいけないのか途方に暮れています。アクセサー メソッドも作成しようとしましたが、それは複雑なようにしか見えませんでした。

#include <iostream>
using namespace std;

class Tile
{
    private:
        int position;
        int tileID;
    public:
        Tile(int, int);
};

// tile constructor
Tile::Tile(int p, int id) : position(p), tileID(id) {}

class TileGame
{
    private:
        const int MAX_TILES;
        Tile* tiles[];
    public:
        TileGame();
        void shuffle();
};

// game constructor
TileGame::TileGame() : MAX_TILES(8)
{
    Tile* tiles[MAX_TILES];
    for (int i = 0; i < MAX_TILES; i++)
    {
        tiles[i] = new tile(i, i);
    }

    // spit out the addresses for each
    cout << endl << "From TileGame(): " << endl;
    for (int i = 0; i < MAX_TILES; i++)
    {
        cout << tiles[i] << endl;
    }
}

void TileGame::shuffle()
{
    // spit out the addresses for each
    cout << endl << "From TileGame(): " << endl;
    for (int i = 0; i < MAX_TILES; i++)
    {
        cout << tiles[i] << endl; // <-- This seems to be the problem
    }
}

int main()
{
    TileGame* game = new TileGame();
    game->shuffle();
}

これはコンパイルされるはずです (再入力する必要があったので、間違いがなければいいのですが)。得られる出力は次のようなものです。

From TileGame():
0x7f9349c03aa0
0x7f9349c03ab0
0x7f9349c03ac0
0x7f9349c03ad0
0x7f9349c03ae0
0x7f9349c03af0
0x7f9349c03b00
0x7f9349c03b10

From shuffle():
0x7fff9502752c
0x100
0
0
0
0
0
0

値にアクセスしようとしてセグメント障害が発生し続けたときに、この時点に到達しましたtiles[]。考え?

4

2 に答える 2

4

コンストラクターは、と呼ばれるメンバーを初期化するために何もしていませんtiles。代わりに、同じ名前のローカル配列を設定しています。コンストラクターが終了すると、これは破棄され、割り当てられたメモリがリークします。次に、初期化されていないメンバーを使用しようとすると、未定義の動作 (この場合はセグメンテーション違反) が発生します。

コンパイル時にサイズがわからない場合、メンバーは配列ではなくポインターである必要があります。

Tile ** tiles;

次のように割り当てられます。

tiles = new Tile* [MAX_TILES];

各タイル ( delete tiles[i]) と配列自体 ( delete [] tiles) をデストラクタで削除することを忘れないでください。自分でリソースを管理するときはいつものように、3 つのルールを覚えておいてください。

さらに良いstd::vectorことに、自分でメモリを管理する必要がないように使用してください。一般に、必要のない場合は動的割り当てを避ける必要があります。たとえば、 でTileGame作成したは、そこにあるメモリ リークを修正するためmainの自動変数 ( ) にすることができます。TileGame game;

于 2012-09-06T17:23:57.133 に答える
1

tilesコンストラクターで作成される配列は、オブジェクト内の配列でTileGameはありません。コンストラクター内のものを取り除きます。tilesGame

また、あまりにもポインタがあります。tiles配列はオブジェクトを保持できTileます。インダイレクションとnews は必要ありません。同様に、 がgameポインターである必要はありません。TileGameオブジェクトとして作成するだけです。

于 2012-09-06T17:23:46.710 に答える