-1

クラス内の動的配列にコピーコンストラクターとoperator=を実装するには、いくつかの助けが必要です。この時点でベクトルを使用することは許可されていません

myeコードは次のとおりです。クラス:

    class Matrix{
    private:
        int rows;
        int columns;
        double* matrix;
    public:
        Matrix();
        explicit Matrix(int N);
        Matrix(int M, int N);
        void setValue(int M, int N, double value);
        double getValue(int M, int N);
        bool isValid() const;
        int getRows();
        int getColumns();
        ~Matrix();
        friend ostream& operator<<(ostream &out, Matrix&matrix1);       
};

そして私のコード:

Matrix::Matrix(){
    matrix = NULL;
}

Matrix::Matrix(int N){
    matrix = new double[N * N];
    rows = N;
    columns = N;

    for(int i = 0; i < N; i++){
        for(int j = 0; j < N; j++){
            if(i==j)
                matrix[i * N + j] = 1;
            else
                matrix[i * N + j] = 0;
        }
    }
}

Matrix::Matrix(int M, int N){
    matrix = new double[M * N];
    rows = M;
    columns = N;

    for(int i = 0; i < M; i++){
        for(int j = 0; j < N; j++)
            matrix[i * N + j] =  0;
    }
}

Matrix::~Matrix(){
    delete [] matrix;
}

void Matrix::setValue(int M, int N, double value){
    matrix[M * columns + N] = value;
}

double Matrix::getValue(int M, int N){
    return matrix[M * columns + N];
}

bool Matrix::isValid() const{
    if(matrix==NULL)
        return false;
    else
        return true;
}

int Matrix::getRows(){
    return rows;
}

int Matrix::getColumns(){
    return columns;
}

ostream& operator<<(ostream &out, Matrix&matrix1){
    if(matrix1.isValid())
        for(int i = 0; i < matrix1.getRows(); i++){
            for(int j = 0; j < matrix1.getColumns(); j++)
                out << matrix1.getValue(i,j) << "\t";
            out << endl;
        }
    else
        out << "Matrisen er ikke gyldig."; //the matrix is not valid
    return out;
}

このようなものは機能しますか?

Matrix &operator=(const Matrix &m) {*(this->matrix) = *(m.matrix);}
Matrix(const Matrix &rhs) : matrix(0) {
        this->matrix = new double();
        *(this->matrix) = *(rhs.matrix);
    }

また、演算子+=および+をオーバーロードします。私はこれを次のように実装しようとしました:

const Matrix operator+=(Matrix matrix1, Matrix matrix2){
        if(!matrix1.isValid() || !matrix2.isValid()){
            cout << "En av matrisene er ugyldig"; //one of the matrices are invalid
            return Matrix::Matrix(); //returning a NULL matrix
        }
        else{
            if(matrix1.getColumns()==matrix2.getColumns() && matrix1.getRows()==matrix2.getRows()){
                Matrix temp(matrix1.getRows(), matrix1.getColumns());
                for(int i = 0; i < matrix1.getRows(); i++){
                    for(int j = 0; j < matrix1.getColumns(); j++)
                        temp.setValue(i,j,(matrix1.getValue(i,j) + matrix2.getValue(i,j)));
                }
                return temp;
            }
            else{
                cout << "Matrisene har ikke samme dimensjon"; //the matrices does not have the same dimensions
                return Matrix::Matrix();
            }
        }
    }
    const Matrix operator+(Matrix matrix1, Matrix matrix2){
        return matrix1 += matrix2;
    }

このようなものは機能しますか?クラスの一部として、クラスの友達として、またはクラスのすぐ外で演算子をオーバーロードする方が良いですか?

どんな助けでも適用されます。

4

2 に答える 2

1
Matrix &operator=(const Matrix &m) {*(this->matrix) = *(m.matrix);}

これにより、lhsの行列の最初の要素のみがrhsの行列の最初の要素と同じになるように割り当てられます。さらに、これには、両方の行列が同じ数の行と列で初期化されている必要があります。memcpyまたはループを使用して、すべての要素を割り当てることができます。

Matrix(const Matrix &rhs) : matrix(0) {
    this->matrix = new double();
    *(this->matrix) = *(rhs.matrix);
}

新しく構築されたインスタンスのマトリックスメンバーに十分なメモリを割り当てていないため、これは失敗します(他のマトリックスが1x1マトリックスでない場合)。行列が行優先の順序で格納されていると仮定すると、次のようになります。

Matrix(const Matrix &rhs) : matrix(0), rows(rhs.rows), columns(rhs.columns) {
    this->matrix = new double[rows * columns];
    for (size_t r = 0; r < rows; r++) {
       for (size_t c = 0; c < columsn; c++) {
          this->matrix[r * columns + c] = rhs.matrix[r * columns + c];
       }
    }
}

編集:念のため、代入演算子を実行する方法は次のとおりです。

Matrix &operator=(const Matrix &m) {
    if (rows * columns != m.rows * m.columns) {
        delete [] this->matrix;
        this->matrix = new double[m.rows * m.columns];
    }
    rows = m.rows;
    columns = m.columns;
    for (size_t r = 0; r < rows; r++) {
       for (size_t c = 0; c < columsn; c++) {
          this->matrix[r * columns + c] = m.matrix[r * columns + c];
       }
    }
    return *this;
}
于 2013-03-13T11:06:10.537 に答える
1

なぜ他の質問を削除したのですか?私はそれが単なるエラーだったことを願っています:(最後の編集を参照してください)

はい、コード、さらにはデザインにも多くの問題があります。

あなたにアイデアを与えるためだけに:

マトリックスにはコピーコンストラクター(または移動)がなく、「<code>=」もありません。彼らです:

Matrix(const Matrix &m);

そして(コンストラクターを移動):

Matrix(Matrix &&m);

Matrix& operator=( const Matrix &m);
Matrix& operator=( Matrix &&m);

これらの特殊関数を定義しない場合、コンパイラーが自動的に定義します。しかし、それらは明らかに機能するだけです。プログラムはコンパイルされますが、正しく動作しません(浅いコピーと深いコピーの問題、および値または参照による受け渡し)。コンストラクターでプライベート配列newを作成するために使用します。matrixそして、デストラクタではあなたはdelete[]matrix。値を渡すたびにMatrix、コンパイラーが生成したコピーコンストラクターを使用してコピーされます。のメンバーの値をコピーするだけMatrixで、ポインターの値がコピーされます。matrixしかし、アレイではありません。呼び出しの終わりに、このローカルコピーは破棄され、元のマトリックスは削除されます!! これは、多くの問題の1つにすぎません。あなたが座って、くずをもっと読んで、後でもう一度やり直すのに十分です。おそらく置き換えるための「単純な」修正

 double *matrix;

std::vector<double> matrix;

これで、コンパイラによって生成された関数がはるかにうまく機能するようになります。

はい、一緒に使用[]したい場合Matrixは、それを定義する必要があります。そして+=、は2項演算子であり、1つのパラメーターを取ります(左側は常にthis、オブジェクトへのポインターであり、それを呼び出します)。ここでは、2つの引数を持つ無料+()または1つの引数を持つメンバーが必要+()です。これがお役に立てば幸いです。聞き返します。

編集:これはとして機能しますoperator=か?

Matrix &operator=(const Matrix &m) {*matrix = *(m.matrix);}

いいえ、これは最初のダブルのみをコピーします。entery配列をループして、各要素をコピーする必要があります。そして最初に、行列のサイズに互換性があることを確認する必要があります。(使用する場合vector matrix=m.matrixは動作します。)コピーコンストラクターの修正は次のようになります。

Matrix::Matrix(const Matrix &m):   rows    (m.rows), 
                                   columns (m.columns), 
                                   matrix  (new double[rows* columns]) 
{
    for(int i = 0; i < rows; i++)
        for(int j = 0; j < columns; j++)
            matrix[i * columns + j] =  m.matrix[i * columns + j];

} 

そして移動するには:

Matrix::Matrix(     Matrix &&m):   rows    (m.rows), 
                                   columns (m.columns), 
                                   matrix  (m.matrix) 
{
     m.matrix=nullptr;
     m.rows= m.columns=0;
} 

この移動により、たとえば時間オブジェクトの場合のように、元の値を気にしない場合に、マトリックスの対処効率を劇的に向上させることができます。この場合、各配列要素のコピーを繰り返す必要はありません。単純に配列全体を盗みます。それの良いところは、ほとんどの場合、コンパイラーが正しいバリアント(コピーまたは移動)を「自動的に」選択することです。

于 2013-03-13T11:02:05.863 に答える