2011-12-20 19 views
0

次のコードで私が間違っていることを指摘できますか?2D配列を動的に割り当てる

int* a = NULL; 
int* b = NULL; 
a = new int[map->mapSize.width]; 
b = new int[map->mapSize.height]; 

layer->tileGids = new int[a][b]; 

は、ここでは、コードが使用する情報:

typedef struct _size { 
    int width, height; 
} size; 

class Map { 
    size mapSize; 
} 

class Layer { 
    int * tileGids; 
} 

EDIT:(コードの最初のビットの行6で)コンパイラエラー:

  • エラー:新しい宣言における発現整数型または列挙型を持つ必要があります。
  • エラー: 'b'は定数式では使用できません。

ソリューション:

私はlightalchemistの答えを受け入れることを決めました。本質的に、私のために働くのは、配列の代わりにベクトルを使うことです。ベクターはあなたのためにメモリを管理しているため、扱いが簡単です。

+2

-1。これをコンパイルしようとするとどうなりますか?コンパイラからエラーが出るのか、それを実行するときに問題がありますか?どんな症状が現れているか教えてください。 –

+0

私の悪い回答には申し訳ありません:P私はそれを削除:) –

+0

また、定義する前に 'size'を使用しました。あなたのコードには多くの改善が必要です。 –

答えて

1

まず、変数 "a"と "b"はポインタです。あなたのコード: layer-> tileGids = new int [a] [b] は問題の根本原因です。

私はここであなたの意図を推測しようとしています。あなたがしようとしているのは、レイヤーのサイズグリッド(mapSize.Width、mapSize.height)を参照する2次元配列です。 layer.tileGids [x] [y]を使用して、グリッド内の各「セル」を参照することができます。

実際に2次元配列を作成しようとする場合は、2つの方法があります。

方法1:

class Layer { 
int ** tileGids; // NOTE the "**" to indicate tileGids is a pointer to pointer i.e. 2D array. 
} 

はそれを初期化するには:

int value = layer.tileGids[x][y] // where 0 <= x < width and 0 <= y < height 

このデータの割り当てを解除するには:

int width = map->mapSize.width; 
int height = map->mapSize.height; 
layer.tileGids = new int*[width]; // NOTE the "int*" to indicate tileGids is a new array of pointers to int. 
for (int i = 0; i < width; i++) // Initialize each element in layer.tileGids[] to be a pointer to int. 
{ 
    layer.tileGids[i] = new int[height]; 
} 

は、今あなたが使ってlayer.tileGidsのアイテムにアクセスすることができますあなたがそれをどのように割り当てるかと同様に、あなたはdealloc

for (int i = 0; i < width; i++) 
    { 
     delete [] layer.tileGids[i]; // Deallocate each row. 
    } 

delete [] layer.tileGids; // Deallocate "array" to the pointers itself. 

方法2:

次に別の簡単、より少ない厄介な方法は、(ポインタを避ける)C++ベクトルクラスを使用することで、各「行」における各動的に割り当てられた配列を食べました。

#include <vector> 
class Layer { 
    vector<vector<int> > tileGids; // Note the space at "<int> >". 
} 

を初期化するには:あなたは、以下の変更を加える必要があるベクターを用いて、第二の方法のために、あなたが持っていないことを

int value = layer.tileGids[x][y]; // Where 0 <= x < width and 0 <= y < height 

注:

int width = map->mapSize.width; 
int height = map->mapSize.height; 
layer.tileGids = vector<vector<int> >(width, vector<int>(height, 0)); // Initialize all entries to 0. 

が要素にアクセスするにはベクトルが自動的に世話をするため、最初のメソッドで必要とされるようなメモリクリーンアップを行う必要があります。しかし、ベクトルが動的に成長することができる、つまりアイテムを追加することができるので、固定サイズの配列を持つ安全性が失われます。つまり、ベクトルメソッドを使用すると誤ってグリッドのサイズを大きくすることができます。しかし、上記の最初の方法を使用して初期化した場合、エラーが発生し、何かが間違っていることがすぐにわかります。

+0

ありがとうございます。 'vector'は2D配列よりも安全であるように見えます。もう一度聞くことができますか、私はやりますか、私のレイヤークラスのデストラクタで明確な方法や類似のメソッドを呼び出す必要はありませんか? – Ben

+0

こんにちは。ベクトルメソッドを使用している場合は、ベクトルオブジェクト自体を動的に割り当てない限り、メモリ管理を行う必要はありません。具体的には、あなたのqnに答えて、上記のコードをそのまま使用すれば、メモリを解放することを示唆する何か「clear」や何かを呼び出す必要はありません。私は "ポインタ"アプローチを使用してメモリを解放するコードを提供するために私の答えを更新します。 – lightalchemist

+0

更新をありがとう、私はあなたのベクトルコードに固執するつもりです。 – Ben

0

a、bは、ここint*です:

layer->tileGids = new int[a][b]; 

おそらく、あなたはこれを言うためのもの?

layer->tileGids = new int[*a][*b]; 
1

Can someone please point out what I am doing wrong in the following code?

たくさん。あなたは2つの単一の配列(必要なものではなく、 "行配列"と "列配列")を割り当てています。そして、あなたは何か変なことをしようとします。 (型システムは、まだコンパイル時に知られるように、寸法と一緒に、タイプが必要になるため)


一般的に、あなたが(厳密に)することはできません動的にC++での2次元配列を割り当てます。あなたは配列の配列またはそれをエミュレートすることができるが、最良の方法は、1次元アレイを割り当てることである。

int width=5; 

std::vector<int> tab(width*height); 

し、手動座標を計算することによって要素にアクセス:

// access the element (1,2) 
tab[1 + 2*width] = 10; 

この方法を基本的に1次元配列を2次元配列として解釈しています(静的な2次元配列と同等の性能)。

次に、便宜上、インデックスをクラスにラップすることをお勧めします。 boost::multi_arrayにもこれが既に行われています。

+0

C++で2D配列を使用することはできませんか?私はあなたがmsitakenであると信じている、またはあなたが意味するものをclaifyする必要があります。 'new char [30] [20]'は2D配列になります。 –

+0

int main(){int ** arr2 = new int [10] [10];}は次のようなエラーを返します。 エラー:初期化で 'int(*)[10]'を 'int **'に変換できません。 –

+1

@MooingDuck:2D配列を使用できますが、行数はコンパイル時定数でなければなりません。各行の列の数だけ動的にすることができます。これは、ゼロ以外の行にインデックスを付けるときに、オフセットを正しく計算するために、コンパイラがストライド(各行の長さ)を知る必要があるためです。 –

2

配列のサイズを初期化するためのポインタを渡すことはできません。他の人はこれを今言及している。

この記事は(それは私のものではありません)、それはあなたを助けるかもしれないように思える:http://eli.thegreenplace.net/2003/07/23/allocating-multi-dimensional-arrays-in-c/

ます。また、クラスレイヤのコンストラクタで割り当てを行うと、その後のデストラクタ(すなわちRAIIでメモリの削除を検討すべきである - 資源獲得があります初期化)。これは良いスタイルと考えられています。

最後に、連続したメモリとカスタムインデックス作成スキームを使用することを検討します。このスキームでは、レイヤーをカプセル化して簡単に使用できます。これはもちろん、どのように大きなものが得られるかに依存します。彼らが大きくなるほど、連続的な記憶のケースがより良くなる。

これはあなたに味を与えるはずです。

#include <iostream> 
#include <cstdlib> 

int main() 
{ 
    const size_t ROWS = 5; 
    const size_t COLS = 2; 
    const size_t size = ROWS*COLS; 

    int* arr = new int[size]; 

    int i = 0; 
    for (size_t r = 0 ; r < ROWS; ++r) 
    { 
     for (size_t c = 0; c < COLS; ++c) 
     { 
     arr[r*COLS+c] = i++; 
     } 
    } 

    for (int j = 0; j < i; ++j) 
    { 
     std::cout << arr[j] << std::endl; 
    } 

    delete [] arr; 
} 
+0

"クラスレイヤのコンストラクタで割り当てを行った後、デストラクタ内のメモリを削除することも考慮する必要があります(RAII - リソース取得は初期化です)。これは良いスタイルと考えられます。 - ありがとう! (+1) – Ben