0

マトリックスのように動作するカスタム クラスを作成しました。いくつかの基本的な操作があり、すべてがうまく機能しているようです...それにもかかわらず、割り当てられたすべてのメモリを解放するために、このクラスのデストラクタに何を書き込めばよいかわかりません。アドバイスをお願いします。

class CMatrix {
public:

class Proxy {
    friend class CMatrix;

    const CMatrix* cmat;
    CMatrix *matrix;
    size_t n;

    Proxy(const CMatrix& m, size_t i)
    : cmat(&m), matrix(), n(i) {
    }

    Proxy(CMatrix& m, size_t i)
    : cmat(&m), matrix(&m), n(i) {
    }

    public:

    const double& operator[](size_t j) const {
       return cmat->_arrayofarrays[n * cmat->y + j];
    }

    double& operator[](size_t j) {
        if (matrix) {
            return matrix->_arrayofarrays[n * cmat->y + j];
        } else return cmat->_arrayofarrays[cmat->y];
    }
    };

    const Proxy operator[](size_t i) const {
        return Proxy(*this, i);
    }

    Proxy operator[](size_t i) {
        return Proxy(*this, i);
    }

    CMatrix() {
    _arrayofarrays = NULL;
    x = 0;
    y = 0;
};

// constructor

CMatrix(size_t x, size_t y) : _arrayofarrays(), x(x), y(y) {
    _arrayofarrays = new double[ x * y ]();
}

// destructor

~CMatrix() {
    // ?!?!???!?!?!?!!!!?!?!? 
    // #$#%@^$!!!!@$#%!!
}

// copy constructor

CMatrix(const CMatrix& other) : _arrayofarrays(), x(other.x), y(other.y) {
    delete [] _arrayofarrays;
    _arrayofarrays = new double[x * y];
    if (_arrayofarrays)
        std::copy(other._arrayofarrays, other._arrayofarrays + (x * y), _arrayofarrays);
}

CMatrix& operator =(const CMatrix& rval) {
    delete [] _arrayofarrays;
    _arrayofarrays = new double[ rval.x * rval.y];
    std::copy(rval._arrayofarrays, rval._arrayofarrays + (rval.x * rval.y), _arrayofarrays);
    x = rval.x;
    y = rval.y;
    return *this;
}



double *_arrayofarrays;
size_t x;
size_t y;
};

編集:

実際、コードのこの部分を実行するとクラッシュすることに気付きました。このコードを呼び出す前に、クラスのインスタンスがありました。a,b,cそれを呼び出して、設定したいと思いa = b-cます。これは初めてうまくいきます...しかし、繰り返したいときはクラッシュします

CMatrix CMatrix::operator-(const CMatrix &matrix) const {
if (this->x != matrix.x || this->y != matrix.y) {
    throw CSizeException(matrix.y, matrix.x, this->y, this->x, '+');
};
CMatrix m(this->x, this->y);
CMatrix l(matrix.x, matrix.y);
l._arrayofarrays = this->_arrayofarrays;
CMatrix o(matrix.y, matrix.y);
o = matrix;


CMatrix result(this->x, this->y);
for (unsigned int i = 0; i < this->x; i++)
    for (unsigned int j = 0; j < this->y; j++)
        m[i][j] = l[i][j] - o[i][j];           
return m;
}
4

2 に答える 2

4

このようなもの?

~CMatrix() {
    delete[] _arrayofarrays;
}

で割り当てられたすべての配列はnew[]、一致する への呼び出しによって破棄する必要がありますdelete[]delete[]さらに、コピー コンストラクターからステートメントを削除できます。

CMatrix(const CMatrix& other) : _arrayofarrays(), x(other.x), y(other.y) {
    // delete [] _arrayofarrays;
    // ^^^^^^^^^^^^^^^^^^^^^^^^^
    // This is unnecessary: you are creating a new object, so this data member
    // is not pointing to any previously allocated array

    // ...
}

アップデート:

コメントから)このコードは使用できません..._arrayofarrays実際には2D配列であるため、これによりプログラムの実行が失敗します..おそらくsegfault

これは正しくありません:_arrayofarraysは 1D 配列であり、呼び出しdelete[]はそれを破棄する適切な方法です。そうすることでセグメンテーション違反が発生する場合は、おそらくコードの残りの部分で何か間違ったことをしている可能性があります。

アドバイスとして、生のポインター 、、および(またはそれらの対応する配列)による手動のメモリ管理は避けることをお勧めします。これは、エラーが発生しやすく、メモリ リークや無効なポインター/参照の逆参照が発生しやすいためです。newdelete

std::vector<>またはなどの標準コンテナの使用を検討してくださいstd::deque<>


編集:

operator -あなたがやっているコードでは:

l._arrayofarrays = this->_arrayofarrays;

このようにして、同じ配列をカプセル化する2 つのマトリックス オブジェクトが作成されます。したがって、2 つのうちの 1 つを削除すると、もう 1 つも無効になります。これがおそらく問題の根本原因です。

また、そこにあまりにも多くの一時的なものを作成しています。何かが足りない場合を除き、これで十分です。

CMatrix CMatrix::operator-(const CMatrix &matrix) const {
    if (this->x != matrix.x || this->y != matrix.y) {
        throw CSizeException(matrix.y, matrix.x, this->y, this->x, '+');
    };

    CMatrix result(this->x, this->y);
    for (unsigned int i = 0; i < this->x; i++)
        for (unsigned int j = 0; j < this->y; j++)
            result[i][j] = (*this)[i][j] - matrix[i][j];

    return result;
}
于 2013-04-07T19:22:38.853 に答える
2

デストラクタでメモリを削除する方法は、他のメンバー関数で記述した方法と同じです。

    delete [] _arrayofarrays;

これがクラッシュする場合は、別の場所でメモリを破損している必要があります。valgrindを使用して、メモリ エラーをチェックしてみてください。

コピー コンストラクターにはいくつかの問題があります。

CMatrix(const CMatrix& other) : _arrayofarrays(), x(other.x), y(other.y) {
    delete [] _arrayofarrays;

これは役に立ちません。削除するものはまだありません。

    _arrayofarrays = new double[x * y];
    if (_arrayofarrays)

これifは役に立たず、new例外をスローするか、null 以外のポインターを返すため、null かどうかを確認しても役に立ちません。

        std::copy(other._arrayofarrays, other._arrayofarrays + (x * y), _arrayofarrays);
}

代入演算子にもいくつかの問題があります。

CMatrix& operator =(const CMatrix& rval) {
    delete [] _arrayofarrays;
    _arrayofarrays = new double[ rval.x * rval.y];

new割り当てで例外がスローされた場合_arrayofarrays、ダングリング ポインターを保持したままにします。古いメモリを削除する前に新しいメモリを割り当てるか、使用後に古いポインターをゼロにする必要があります。delete[]

于 2013-04-07T19:31:21.087 に答える