この問題は非常に初級レベルの問題ですが、初心者で知らない人にとっては頭を悩ませるかもしれません。C++ では関数は配列を直接返すことはできませんが、配列は実際にはポインタなので、関数にポインタを返させることで実現できます。例えば、行列の掛け算を行う関数は、簡単に次のように書きます:
例
using namespace std;
float* MultMatrix(float A[4], float B[4])
{
float M[4];
M[0] = A[0]*B[0] + A[1]*B[2];
M[1] = A[0]*B[1] + A[1]*B[3];
M[2] = A[2]*B[0] + A[3]*B[2];
M[3] = A[2]*B[1] + A[3]*B[3];
return M;
}
int main()
{
float A[4] = { 1.75, 0.66, 0, 1.75 };
float B[4] = {1, 1, 0, 0};
float *M = MultMatrix(A, B);
cout << M[0] << " " << M[1] << endl;
cout << M[2] << " " << M[3] << endl;
return 0;
}
しかし実行してみると結果は次のようになります:
1.75 1.75 6.51468e-039 3.76489e-039
これは本来望んでいた結果ではありません。そこで関数内にも表示コードを追加して、計算の問題かどうかを確認してみると、次の結果が得られます:
1.75 1.75 0 0 1.75 1.75 1.96875 1.75
計算結果は正しいことが分かりましたが、返却後は変わってしまい、前回の結果とも異なります。これはなぜでしょうか?
関数内で定義した配列 M は関数の実行が完了した時点でシステムによって解放されてしまうため、呼び出し元の関数で得られる結果は当然計算後の結果ではありません。1つの解決策はメモリを動的確保することです。関数内で配列を new すれば、解放されなくなります。
そこで、次のように変更する必要があります:
float M[4];
次のように変更します:
float *M = new float[4];
修正して実行すると、次の結果が得られます:
1.75 1.75 0 0 1.75 1.75 0 0
正しいです。しかし、この方法では自分で確保した領域を解放していません。関数内で解放すると、結果は最初のときと同じになってしまいます。
呼び出しコードを見てみましょう:
float *M = MultMatrix(A, B);
これは実際には M ポインタを関数内の M 配列の先頭アドレスを指すようにしているだけです。M ポインタを解放しても、確保した M 配列を解放するのと同じ効果があります。なぜなら、それらは同じメモリ領域を指しているからです。そこでコードは次のように修正します:
例
using namespace std;
float* MultMatrix(float A[4], float B[4])
{
float *M = new float[4];
M[0] = A[0]*B[0] + A[1]*B[2];
M[1] = A[0]*B[1] + A[1]*B[3];
M[2] = A[2]*B[0] + A[3]*B[2];
M[3] = A[2]*B[1] + A[3]*B[3];
cout << M[0] << " " << M[1] << endl;
cout << M[2] << " " << M[3] << endl;
return M;
}
int main()
{
float A[4] = { 1.75, 0.66, 0, 1.75 };
float B[4] = {1, 1, 0, 0};
float *M = MultMatrix(A, B);
cout << M[0] << " " << M[1] << endl;
cout << M[2] << " " << M[3] << endl;
delete[] M;
return 0;
}
実行結果:
1.75 1.75 0 0 1.75 1.75 0 0
問題ありません。new した領域も delete で解放されています。
以下の達人たちのアドバイスを踏まえて、プログラムを次のように修正しました。皆さんどう思いますか:
例
using namespace std;
void MultMatrix(float M[4], float A[4], float B[4])
{
M[0] = A[0]*B[0] + A[1]*B[2];
M[1] = A[0]*B[1] + A[1]*B[3];
M[2] = A[2]*B[0] + A[3]*B[2];
M[3] = A[2]*B[1] + A[3]*B[3];
cout << M[0] << " " << M[1] << endl;
cout << M[2] << " " << M[3] << endl;
}
int main()
{
float A[4] = { 1.75, 0.66, 0, 1.75 };
float B[4] = {1, 1, 0, 0};
float *M = new float[4];
MultMatrix(M, A, B);
cout << M[0] << " " << M[1] << endl;
cout << M[2] << " " << M[3] << endl;
delete[] M;
return 0;
}
コメント内容:
まず、配列の delete は delete[] です。
次に、C++ における手動メモリ確保の重要な原則は、確保した人が解放するということです。
したがって、MultMatrix 内で配列を new すべきではなく、外部で new した後に渡して変更するべきです。
配列を返したい場合は、スマートポインタのようなものを使うのが正攻法です。
原文アドレス:https://www.cnblogs.com/yangxi/archive/2011/09/18/2180759.html