0

私は行列クラスを持っており、次のコンストラクターを使用しています。

template<class T>
Matrix<T>::Matrix(unsigned rows, unsigned cols) :
        rows(rows), cols(cols) {
    index = 0;
    data_ = new T[rows * cols];
}

template<class T>
Matrix<T>::~Matrix() {
    delete[] data_;
}

行列の逆行列を計算するとき、次のような一時変数のメモリを解放したいと思いますa

template<class T>
Matrix<T> Matrix<T>::inverse() {
    unsigned i, j, k;
    Matrix<T> a(2 * rows, 2 * rows);        
    ....
    return tmp;
}

この変数は関数の最後で破棄されると思いましたが、テストすると次のようになります。

for (int i = 0; i < 3; i++) {   
        Matrix<double> m(5, 5);
        m << 5, 2, 4, 5, 6, 1, 3, 1, 2, 5, 2, 5, 2, 7, 2, 9, 2, 1, 0.1, 0.43, 1, 0, 0, 0, 1;
        m.inverse();
        std::cout << m << std::endl;
    }

最初のループでaは、はゼロで初期化されますが、次のステップでは、の初期値はa前の値であるため、a(k+1)=a_endvalues(k)。なんでこんな感じ?

4

5 に答える 5

3

メモリは実際に解放されます。そして、ループの次の繰り返しで再度割り当てられます。コンストラクターが配列を初期化しないわけでMatrixはないため、現在それに属しているメモリにたまたま格納されていたものが含まれているだけです。

特定のケースでは、アロケータa.data_が最初の反復と同じ場所に2 番目の反復を配置する可能性がa.data_あるため、古い値が引き続き表示されます。

于 2012-11-23T12:39:51.703 に答える
2

関数が呼び出されるたびに、メモリが解放され、再割り当てされます。価値観の重なりは偶然です。新しい割り当ては、古い割り当てと同じ場所にある可能性があります。別のパラメーター化されたコンストラクターを作成し、別の初期化子を渡すことで、これをテストできます。

出力ステートメントを記述して、デストラクタが呼び出されるかどうかをテストすることもできます。

于 2012-11-23T12:43:22.843 に答える
2

問題は、コンストラクターで動的に割り当てられた配列の要素を初期化していないことです。配列にデフォルトで構築された要素またはゼロで初期化された要素があることを確認するには、コンストラクターでこれを行う必要があります。

template<class T>
Matrix<T>::Matrix(unsigned rows, unsigned cols) :
        rows(rows), cols(cols) {
    index = 0;
    data_ = new T[rows * cols]();
                //             ^ HERE!
}

しかし、コメントで指摘されているように、次を使用することで生活を楽にすることができますstd::vector<T>:

template<class T>
Matrix<T>::Matrix(unsigned rows, unsigned cols) :
        rows(rows), cols(cols), data_(rows*cols) 
{ }
于 2012-11-23T13:03:07.317 に答える
1

配列の初期化は、配列の割り当てとは別のものです。

デストラクタにデバッグ出力を追加して、それが呼び出されたことを確認します。

また、配列をゼロに初期化するには、memset を使用します。

memset(a, 0, rows * cols * sizeof(T));
于 2012-11-23T12:40:20.247 に答える
1

ローカル変数 'a' が破棄され、デストラクタがメモリを解放します。ただし、メモリが再度割り当てられたとき、メモリの場所に以前の内容があるのは偶然です。

于 2012-11-23T12:42:50.843 に答える