![](http://oshiete.xgoo.jp/images/v2/pc/qa/question_title.png?e8efa67)
No.9
- 回答日時:
No7です。
> 1次元配列に置き換えるということですね。
> これだと要素数が2のn乗でない場合には遅くなるかもしれませんね。
> (すみません。試していません)
> クラスにして要素へのアクセスを[]演算子でできるようにして・・・という感じでしょうか?
1次元にすると各要素ごとのメモリ確保・解放が出来ないので
常に最大量食いっぱなしなのが美しくないですけどね^^;
処理が遅い、というのはアセンブラに直してみると解ると思いますが、
値を取るたびに乗算が複数回行われるので
3次配列に比べて遅いかなぁ、と思って書きました。
#すみません試してません…
2のn乗でない場合も遅いかもなんですね。
場合によって使い方はマチマチなのですが、
手っ取り早くそのまま使ってることが多いです。
色々端折ってますが以下のような感じです。
void CHogeHoge::Create3DArray( int nRangeX, int nRangeY, int nRangeZ )
{
m_pBuffer = new int[ nRangeX * nRangeY * nRangeZ ];
m_nRangeX = nRangeX; // 配列の一次要素数 [ ][ ][*]
m_nRangeY = nRangeY; // 配列の二次要素数 [ ][*][ ]
m_nRangeZ = nRangeZ; // 配列の三次要素数 [*][ ][ ]
}
int CHogeHoge::GetValue( int nAxisX, int nAxisY, int nAxisZ )
{
return m_pBuffer[ nAxisX + nAxisY * m_nRangeX + nAxisZ * ( m_nRangeX * m_nRangeY ) ];
}
試してみました。
2次元配列の場合、要素数が2^nとそうでない場合とでは30%程度パフォーマンスが落ちるようです。
乗算のコストとシフトのコストの差、よりはマシですが、命令スケジューリングが効いているのかもしれませんね。
なお、BCB6でMMXのSSE2を使って乗算+右シフトをasmで書いた場合とも比較しましたが、SSE2は50%程度までしか早くなりませんでした。
なかなかうまくいかないものです。
No.7
- 回答日時:
私のやり方が正しいかわかりませんが・・・
いつも多次元配列を考えるのが面倒なので、
int *P = new int[ x * y * z ];
// int P[z][y][x]のようにしたい場合
のように確保して、
int I = P[ X + Y*x + Z*(x*y) ];
// X,Y,Z は取り出したいデータが入ってる各軸の座標
のように取り出してます。
ご参考までに。
#処理が遅いかも…?
ありがとうございます。
1次元配列に置き換えるということですね。
これだと要素数が2のn乗でない場合には遅くなるかもしれませんね。
(すみません。試していません)
クラスにして要素へのアクセスを[]演算子でできるようにして・・・という感じでしょうか?
No.6
- 回答日時:
解決方法というよりも、C の配列の話をします。
ここから、lachesis-r さんのやり方でうまくいかない理由を汲み取ってもらえれば良いのですけど。。。
No4 Tacosan さんの回答がきちんと動作するか、未確認ですが、動作するのであれば、配列を使った解決手段としてはほぼ唯一ではないでしょうか。
C の配列はコンパイラが先頭要素へのポインタに読み替えますが、これは再帰的には適用されません。
つまり、配列の配列の配列 (3次元配列) では、配列の配列の先頭要素へのポインタに読み替えられますが、さらにそこからポインタへの読み替えは起こりません。
つまり、以下のようになるわけです。
[例]
------------------------------------------------
// NEW
int **mat = new int*[elem2][elem1]
for ( i = 0; i < elem2; i++ )
{
for ( j = 0; j < elem1; j++ )
{
mat[i][j] = new int[elem3];
}
}
// DELETE
for ( i = 0; i < elem2; i++ )
{
for ( j = 0; j < elem1; j++ )
{
delete [][] mat[i][j];
}
}
delete mat;
------------------------------------------------
ですので、すでに回答にある方法を参考にするほうが、有用だと思います。
# C++ 自体よく知らないものでして。。。
$ うまい解決方法は、詳しい方々におまかせします。。。
とりあえず参考程度に。。。
この回答への補足
ありがとうございます。
いろんな方法があるものですね・・・
少し整理したいのですが、仕事が忙しくなかなか空き時間がとれません。
delete[][] というのがミソでしょうか。恥ずかしながらはじめて見ました。
No.5
- 回答日時:
> vectorはコンパイル速度も実行速度も犠牲になりますし、アルゴリズムも範囲チェックも不要なので、出来れば避けたいと思います。
実際に計測していただければわかると思いますが、vectorを使っても実行速度はほとんど変わらないはずです。(ライブラリの実装にもよるところも多少ありますし、CINTのようなインタープリタであればやはり遅くなるでしょうが...)
> これだと、添え字の異なる(型が同一の)3次元配列をひとつの関数で受けられません。
> 例えば、a[10][20][30]とb[60][70][10]のような関数を同一の関数に渡す事ができません。
>
> 何か良い方法がありますか?
template <int M, int N> void func(int (*p)[M][N]);
のようにすれば、1つの関数で済みます。(実体は複数出来ます)
この回答への補足
ありがとうございます。
今、仕事がバタバタしておりまして、手が空き次第、試してみます。
実行速度については、以前の予備テストのおぼろげな記憶でして、不適切な発言だったかもしれません。
これについても、再度確認します。
なんとかテスト再開できました。
A,Bが動的2次元配列、AVがvecorによる2次元配列で、
for(int i=0;i<count;i++)
for(int y=0;y<DIM;y++)
for(int x=0;x<DIM;x++)
A[y][x]= A[y][x] *B[DIM][DIM]/256;
for(int i=0;i<count;i++)
for(int y=0;y<DIM;y++)
for(int x=0;x<DIM;x++)
AV[y][x]= AV[y][x] *B[DIM][DIM]/256;
これだと
前者: 805.275ms
後者: 1833.780ms
でした。
(DIM:512、count:1000)
Pen4 3.2G WinXPPro BCB6Pro
ふと思ったのは、vectorはイテレータを使わないと早くならないのかしら?ということですが、そこまで手が回りませんでした^^;
※コンパイル速度は遅いと感じるほどには変わりませんでした。
※vectorは要素チェックは行いませんね。不適切な発言でした。
No.4
- 回答日時:
// 確保
int ***mat;
mat = new int **[a];
mat[0] = new int *[a*b];
mat[0][0] = new int [a*b*c];
for (int i = 0; i < a; i++) {
mat[i] = mat[0] + i*b;
mat[i][0] = mat[0][0] + i*b*c;
for (int j = 0; j < b; j++) {
mat[i][j] = mat[i][0] + j*c;
}
}
// 開放
delete [] mat[0][0];
delete [] mat[0];
delete [] mat;
くらいかなぁ? 実行してないので動作の保証はできませんが....
No.3
- 回答日時:
学習目的であれば別ですが、実用を考えると次のようにした方がよいと思います。
要素数が固定でよい場合...
int (*p)[M][N] = new int[num][M][N];
各次の要素数が可変の場合...
std::vector<std::vector<std::vector<int> > > a;
なるべくstd::vectorを使うことをお薦めします。
(解放の手間も省けることですし...)
この回答への補足
ありがとうございます。
vectorはコンパイル速度も実行速度も犠牲になりますし、アルゴリズムも範囲チェックも不要なので、出来れば避けたいと思います。
int (*p)[M][N] = new int[num][M][N];
の使い方も試してみました。
これだと、添え字の異なる(型が同一の)3次元配列をひとつの関数で受けられません。
例えば、a[10][20][30]とb[60][70][10]のような関数を同一の関数に渡す事ができません。
何か良い方法がありますか?
(未だに***p でのdeteteがうまくいかない・・・)
>a[10][20][30]とb[60][70][10]のような関数を
a[10][20][30]とb[60][70][10]のような「配列」を
です。申し訳ありません。
No.1
- 回答日時:
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- C言語・C++・C# ポインタの型変換、どうやるんでしたっけ? 2 2022/03/28 11:00
- C言語・C++・C# このプログラミング誰か教えてくれませんか 1 2022/06/02 15:27
- Java javaでのプログラム(配列)について質問です. 2 2022/10/14 22:27
- C言語・C++・C# C#テキストボックスの文字を配列にいれてその後表示する 4 2022/07/17 04:47
- Visual Basic(VBA) 列 A に同じ日が2つが必要です。 1 2023/03/28 07:25
- Visual Basic(VBA) 数字が「0」の列を削除するため、下記のコードを実行しましたが、コンパイルエラーSubまたはFunct 3 2022/12/04 00:00
- C言語・C++・C# C言語の課題が出たのですが自力でやっても分かりませんでした。 要素数がnであるint型の配列v2の並 3 2022/11/19 17:41
- C言語・C++・C# c言語の問題です 課題1 (二分探索木とセット) 大きさ size の配列 array を考える。す 2 2023/01/10 21:08
- Java Java 配列<選挙> 4 2023/07/31 15:07
- C言語・C++・C# C 言語の Gauss Jordan 法について 2 2022/12/28 11:16
関連するカテゴリからQ&Aを探す
おすすめ情報
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
関数から配列を返すには?
-
構造体のextern方法
-
c言語
-
C言語 数値の連続入力について
-
C++:構造体:newで入れ子:del...
-
C言語において、 配列要素をひ...
-
define で 配列
-
配列の要素数に変数を入れたい...
-
C言語から質問です。
-
C#で構造体の配列を持った構造...
-
[C++]const int と配列
-
C#でのフィボナッチ数列
-
fclose()でセグメンテーション違反
-
C言語について質問です。
-
C言語 ファイルの指定された行...
-
ファイルのデータを構造体に代...
-
関数内に関数は無理でしょうか...
-
C++DLLからC#へのコールバック...
-
c言語プログラミング 等差数列...
-
MFCのCArrayを使った二次元配列
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
関数から配列を返すには?
-
C言語において、 配列要素をひ...
-
配列の要素数に変数を入れたい...
-
構造体のextern方法
-
define で 配列
-
c言語
-
C#で構造体の配列を持った構造...
-
C言語の2次元配列 容量が大き...
-
c言語 構造体
-
C言語 ファイルの指定された行...
-
C言語についてです 5人のテスト...
-
int i, int i[1];
-
fclose()でセグメンテーション違反
-
char型配列をint型に代入するには
-
C言語から質問です。
-
Cのエラー
-
コンボボックスでデフォルト値...
-
C言語の課題が出たのですが自力...
-
MFCのCArrayを使った二次元配列
-
[C++]const int と配列
おすすめ情報