みんなの「教えて(疑問・質問)」にみんなで「答える」Q&Aコミュニティ

こんにちはゲストさん。会員登録(無料)して質問・回答してみよう!

解決済みの質問

2次元配列のnew

4x4行列のデータがいくらか書いてあるファイルから、読み込んでvector配列へ保存するプログラムを考えています。
vector配列は、float[4][4]の先頭ポインタの配列です。
宣言はこんな感じで、コンパイルエラーは出ませんでした。

vector<float[4][4]> matrix;


つぎに読み込み部分で、下のような感じです。
4x4行列が見つかるたびにこれが実行されます。
GetFloatToken()は、ファイルから要素をひとつ取り出す関数です。

float m[4][4] = new float[4][4];
for(int g=0; g<4; g++)
for(int r=0; r<4; r++)
m[g][r]=GetFloatToken();
matrix.push_back(m);

newの行とpush_backしてる行でエラーが出ました。

自分が思うに、m[4][4]のとこの、newからの受け取りの仕方が悪い気がしました。
そこで、*m[4] や **m とかにして試してみましたがうまくいきませんでした。
どうすればいいんでしょうか。
もしかして、c++では多次元配列のnewは無理なんでしょうか。
わかる方がいましたら、どうか教えてください。

補足:
あとで行列の計算をするのが楽なので、float[4][4]の形は変えたくないです。
もし、多次元配列のnewが無理ということなら別の策を考えます。

投稿日時 - 2011-06-12 18:33:06

QNo.6804665

困ってます

質問者が選んだベストアンサー

> 配列型は代入可能ではないんですか。

たとえば、

float m1[4][4], m2[4][4];

とあった場合、

m1 = m2;

とはできませんよね。

ちなみに、newで生成する場合は次のようにします。

float (*m)[4] = new float[4][4];

投稿日時 - 2011-06-12 20:41:13

お礼

詳しい説明ありがとうございます。
勉強になりました。

要素が
float m[4][4];
だけの構造体をつくるとこで、一応問題は解決しました。
ありがとうございました。

投稿日時 - 2011-06-12 21:54:44

ANo.2

このQ&Aは役に立ちましたか?

0人が「このQ&Aが役に立った」と投票しています

回答(5)

ANo.5

「C++ 二次元vertor」で検索してみましたら、下記の例が見つかりました。
いろいろな方法があるようですね。

http://okwave.jp/qa/q1748241.html

投稿日時 - 2011-06-12 23:42:21

お礼

回答ありがとうございます。

投稿日時 - 2011-06-15 17:50:44

ANo.4

#3ですが、自分の書いたコードについて付記を。

個人的な事情により駆け足で書いたコードのため、投稿後気付いただけでも「行列の各要素にアクセスするメソッドが抜けている」「乗算に桁落ちに対する考慮が全くなされていない」「代入でないほうの乗算は少々非効率的」という問題がありますのでご注意ください。

投稿日時 - 2011-06-12 22:21:37

お礼

回答ありがとうございます。
長いコードを書いて下さりありがとうございます。
自分は、

struct MATRIX4x4{
float m[4][4];
};

vector<MATRIX4x4*> matrix;


MATRIX4x4 *m = new MATRIX4x4;
for(int g=0; g<4; g++)
for(int r=0; r<4; r++)
m->m[g][r]=GetFloatToken();
key->matrix.push_back(m);


とすることで解決しました。
あとで計算するときには、
matrix[0]->m[][]
みたいにしてやるだけなので、float[4][4]の形で使えます。
せっかく書いてくださったのですが、今回は書きなおしが楽なのでこちらを使うことにします。

>「行列の各要素にアクセスするメソッドが抜けている」
privateからpublicにimplを移して解決、でいいような気がします。
現在行列の計算はすべて関数で実装しているので、operatorは全然つかってないんです。
それなので、かなり書きなおさないと使えないんです。
operatorをつかったらもっと見やすいコードになると思いますが、今はやる気がびみょーなので
またやる気があったら書き直すか検討してみたいと思います。

投稿日時 - 2011-06-12 23:13:55

ANo.3

> あとで行列の計算をするのが楽なので、float[4][4]の形は変えたくないです
というのなら、そういうクラスを作ってしまいましょう。
(ぐぐったら主にUNIX/Linux用のよさそうなライブラリがあったのは置いといて。GPLだから利用して問題がないか考慮する必要もあります)

class Matrix4
{
private:
 float impl[4][4];

public:
 Matrix4();
 Matrix4(const Matrix4& src);
 Matrix4(float src[4][4]);
 Matrix4& operator=(const Matrix4& src);
 Matrix4& operator+=(const Matrix4& src);
 Matrix4& operator-=(const Matrix4& src);
 Matrix4& operator*=(const Matrix4& src);
};

Matrix4& operator+(const Matrix4& lhs, const Matrix4& rhs);
Matrix4& operator-(const Matrix4& lhs, const Matrix4& rhs);
Matrix4& operator*(const Matrix4& lhs, const Matrix4& rhs);

Matrix4::Matrix4()
{
 for(int i = 0; i < 4; i++){
  for(int j = 0; j < 4; j++){
   impl[i][j] = 0.0F;
  }
 }
}
Matrix4::Matrix4(const Matrix4& src)
{
 memcpy(impl, src.impl, sizeof(impl));
}
Matrix4::Matrix4(float src[4][4])
{
 memcpy(impl, src, sizeof(impl));
}
Matrix4& Matrix4::operator=(const Matrix4& src)
{
 if (impl != src.impl)
  memcpy(impl, src.impl, sizeof(impl));

 return *this;
}
Matrix4& Matrix4::operator+=(const Matrix4& src)
{
 for(int i = 0; i < 4; i++){
  for(int j = 0; j < 4; j++){
   impl[i][j] += src.impl[i][j];
  }
 }

 return *this;
}
Matrix4& Matrix4::operator-=(const Matrix4& src)
{
 for(int i = 0; i < 4; i++){
  for(int j = 0; j < 4; j++){
   impl[i][j] -= src.impl[i][j];
  }
 }

 return *this;
}
Matrix4& Matrix4::operator*=(const Matrix4& src)
{
 float result[4][4];
 for(int i = 0; i < 4; i++){
  for(int j = 0; j < 4; j++){
   result[i][j] = 0.0F;
   for(int k = 0; k < 4; k++){
    result[i][j] += impl[i][k] * src.impl[k][j];
   }
  }
 }
 memcpy(impl, result, sizeof(impl));

 return *this;
}
Matrix4 operator+(const Matrix4& lhs, const Matrix4& rhs)
{
 Matrix4 result(lhs);
 result += rhs;
 return result;
}
Matrix4& operator-(const Matrix4& lhs, const Matrix4& rhs)
{
 Matrix4 result(lhs);
 result -= rhs;
 return result;
}
Matrix4& operator*(const Matrix4& lhs, const Matrix4& rhs)
{
 Matrix4 result(lhs);
 result *= rhs;
 return result;
}

こんな感じだと思います。
まあ、だれかもっと効率的な実装を書くでしょうが。

参考URL:http://www.gnu.org/software/octave/

投稿日時 - 2011-06-12 21:42:37

ANo.1

vectorの要素は代入可能でなければなりません。
配列型は代入可能ではありませんので、まともにコンパイルできないか、あるいはまともに動きません。

投稿日時 - 2011-06-12 19:28:54

お礼

回答ありがとうございます。
配列型は代入可能ではないんですか。知らなかったです。
関数の引数としては受け取れたので出来るかと思っていました;

代入可能ではないということは、newから受け取るのも難しいってことですよね。

それじゃあ今回は諦めて、別の方法を考えたいと思います。

投稿日時 - 2011-06-12 20:12:15

あなたにオススメの質問