带有矩阵的赋值运算符(=)返回垃圾值

问题描述 投票:1回答:1

我正在用c ++构建类“ Matrix”,并且在创建operator =时遇到了一些麻烦。下面提供了实现,然后是无效的代码,但让我澄清一下问题,因为它很具体:

创建两个新矩阵m1,m2时,操作m1 = m2将m1设置为包含垃圾值。

已经说过,在operator =的范围内,我正在研究的“这个”矩阵似乎拥有正确的值。从操作员=(右侧)返回值到实际将其分配给左侧m1的路径中存在错误。

所以再次,这是整个文件,但具体来说,请注意operator =以及也许是构造函数-我认为这会引起问题。

h文件

// Matrix.h

#ifndef MATRIX_H
#define MATRIX_H

#include <fstream>
#include <iostream>



class Matrix
{
public:
    Matrix(int rows, int cols); //ctor

    Matrix(); //default ctor

    Matrix(const Matrix &m); // copy ctor

    ~Matrix(); //destructor

    int getRows() const;

    int getCols() const;

    Matrix &vectorize(); // convert matrix to vector

    void plainPrint() const; // print matrix

    Matrix &operator=(const Matrix &b); // assignment this = b

    Matrix &operator*(float c); // M*c

    friend Matrix &operator*(float c, Matrix &m); // c*M

    friend Matrix operator+(const Matrix &a, const Matrix &b); //a+b

    friend Matrix operator*(const Matrix &a, const Matrix &b); // a*b

    Matrix &operator+=(const Matrix &b); //this += b

    float& operator()(int i, int j); // this(i,j)

    float& operator[](int i); // this[i]

    float& operator()(int i, int j) const; //const this(i,j)

    float& operator[](int i) const; //const this[i]

    friend std::ostream &operator<<(std::ostream &os, const Matrix &m);

    friend std::istream &operator>>(std::istream &is, const Matrix &m);

private:
    int _rows, _cols;
    float *_mat;

    static void throwError();
    static float getSum(const Matrix &a, const Matrix &b, int k, int i, int j);

};

#endif //MATRIX_H

cpp文件

#include "Matrix.h"
#include <string>
#include <iostream>


using std::string;
using std::cerr;
using std::endl;
using std::cout;
using std::cin;

#define ERR_MSG  "program failed - you've probably done something wrong."
#define INITIAL_SIZE 1

/** ------------------------------------ private functions ------------------------------------**/
/**
 * prints an error message to cerr and exists with exit failure code
 */
void Matrix::throwError()
{
    cerr << ERR_MSG << endl;
    exit(EXIT_FAILURE);
}

/**
 * * used for matrices multiplication. returns the value of c_ij according to
 * c_ij = a_ik * b_kj , where k is a summation index
 * @param a - some matrix
 * @param b - some matrix
 * @param k - amount to sum
 * @param i - current row
 * @param j -current column
 * @return c_ij as specified
 */
float Matrix::getSum(const Matrix &a, const Matrix &b, int k,int i,int j)
{
    float c_ij = 0;
    for (int l = 0; l < k ; l++)
    {
        c_ij+=a.operator()(i,l)*b.operator()(l,j);
    }
    return c_ij;
}

/** ------------------------------------ constructors ------------------------------------**/
/**
 *  constructor for martix instance, initializes all matrix values to zero
 * @param rows - number of rows
 * @param cols - number of columns
 */
Matrix::Matrix(int rows, int cols) :
        _rows(rows), _cols(cols), _mat(nullptr)
{
    if (rows <= 0 || cols <= 0) // checking valid input
    {
        throwError();
    }
    _mat = new(std::nothrow) float[rows * cols]; // allocating memory
    if (_mat == nullptr)
    {
        throwError();
    }
    for (int i = 0; i < rows; i++)
    {
        for (int j = 0; j < cols; j++)
        {
            _mat[i * cols + j] = 0;
        }
    }
}

/**
 *default constructor - initializes a matrix of size 1x1
 */
Matrix::Matrix() : Matrix(INITIAL_SIZE, INITIAL_SIZE)
{}

/**
 * copy constructor
 * @param m some matrix
 */
Matrix::Matrix(const Matrix &m) : Matrix(m._rows,m._cols)
{
    *this = m;
}

/**
 * destructor for class Matrix - frees _mat from memory
 */
Matrix::~Matrix()
{
    delete[] _mat;
    _mat = nullptr;
}
/** ------------------------------------ methods ------------------------------------**/
/**
 * @return amount of rows as int
 */
int Matrix::getRows() const
{
    return _rows;
}

/**
 * @return amount of columns as int
 */
int Matrix::getCols() const
{
    return _cols;
}

/**
 * converts a matrix into a column vector
 * @return
 */
Matrix &Matrix::vectorize()
{
    int newCols = INITIAL_SIZE; // 1 column
    int newRows = _cols * _rows;
    _rows = newRows;
    _cols = newCols;
    return *this;
}

void Matrix::plainPrint() const
{
    cout << endl;
    for (int i = 0; i < _rows; i++)
    {
        for (int j = 0; j < _cols; j++)
        {
            cout << _mat[i * _cols + j] << " ";
        }
        cout << endl;
    }
}

/** ------------------------------------ operators ------------------------------------**/

Matrix &Matrix::operator=(const Matrix &b)
{
    if (this!=&b) // b is not this
    {
        delete[] _mat;
        _mat = nullptr;
        float newValues[b._rows * b._cols];
        for (int i = 0; i < b._rows * b._cols; i++)
        {
            newValues[i] = b._mat[i];
        }
        _mat = newValues;
        _rows = b._rows;
        _cols = b._cols;
    }
    return *this;
}

/**
 * returns this matrix multiplied by c
 * notice that this is a member function, performed on this matrix
 * @param c - some value
 * @return M*c
 */
Matrix &Matrix::operator*(float c)
{
    for (int i = 0; i < _rows; i++)
    {
        for (int j = 0; j < _cols; j++)
        {
            _mat[i * _cols + j] *=  c;
        }
    }
    return *this;
}

/**
 * returns c*M. notice this is not a member function (does not operates on this matrix)
 * @param c - some value
 * @param m - some matrix
 * @return
 */
Matrix &operator*(float c, Matrix &m)
{
    for (int i = 0; i < m._rows; i++)
    {
        for (int j = 0; j < m._cols; j++)
        {
            m._mat[i * m._rows + j] = m._mat[i * m._rows + j] * c;
        }
    }
    return m;
}

/**
 * adds two matrices together
 * @param a some matrix
 * @param b some matrix
 * @return a+b
 */
Matrix operator+(const Matrix &a, const Matrix &b)
{
    if (a._rows != b._rows || a._cols != b._cols)
    {
        a.throwError(); // matrices must be of same dimension
    }
    int rows = a._rows;
    int cols = a._cols;
    Matrix newMat = Matrix(rows, cols);

    for (int i = 0; i < rows; i++)
    {
        for (int j = 0; j < cols; j++)
        {
            newMat._mat[i * cols + j] = a._mat[i * cols + j] + b._mat[i * cols + j];
        }
    }
    return newMat;
}
/**
 * multiplies two matrices
 * @param a - some matrix (must be m*n)
 * @param b - some matrix (must be n*p)
 * @return new matrix a*b (m*p)
 */
Matrix operator*(const Matrix &a, const Matrix &b)
{
    if(a._cols != b._rows)
    {
        a.throwError(); // matrices must be of dimensions a_(m * n) * b_(n * p)
    }
    // assigning letters to correspond the values in description:
    int m = a._rows; // = c._rows
    int n = a._cols; // = b._rows
    int p = b._cols; // = c._cols

    Matrix c = Matrix(m,p);
    for(int i=0;i<m;i++)
    {
        for(int j=0;j<p;j++)
        {
            c._mat[i*p+j] =  c.getSum(a,b,n,i,j);
        }
    }
    return c;
}


Matrix &Matrix::operator+=(const Matrix &b)
{
    for (int i = 0; i < _rows; i++)
    {
        for (int j = 0; j < _cols; j++)
        {
            _mat[i * _cols + j] = _mat[i * _cols + j] + b._mat[i * _cols + j];
        }
    }
    return *this;
}

float &Matrix::operator()(int i, int j)
{
    return _mat[i * _cols + j];
}

float &Matrix::operator[](int i)
{
    return _mat[i];
}

float &Matrix::operator()(int i, int j) const
{
    return _mat[i * _cols + j];
}

float &Matrix::operator[](int i) const
{
    return _mat[i];
}


/**
 * << operator, as specified in part 3.4 of the exercise
 * prints the quessed number to the screen
 * @param os output stream
 * @param m matrix
 * @return os
 */

std::ostream &operator<<(std::ostream &os, const Matrix &m)
{
    int rows = m._rows;
    int cols = m._cols;

    cout<<endl;
    for (int i=0; i<rows-1;i++)
    {
        for(int j=0;j<cols-1;j++)
        {
            if (m.operator()(i,j)<=0.1f)
            {
                cout << "  ";
            }
            else
            {
                cout << "**";
            }
        }
        cout<<endl;
    }
    return os;

}

/**
 * >> operator, reads the input and inserts it into the matrix
 * @param is input stream
 * @param m matrix
 * @return is
 */
std::istream &operator>>(std::istream &is, const Matrix &m)
{
    int rows = m._rows;
    int cols = m._cols;
    for (int i=0; i<rows-1;i++)
    {
        for(int j=0;j<cols-1;j++)
        {
            is.read((char*)&m[i*cols+j],sizeof(float));
            if(! is.good())
            {
                m.throwError();
            }
        }
    }
    return is;


}

您可以尝试运行此主程序以查看问题:

int main()
{
    Matrix m1 = Matrix(4,4);
    Matrix m2 = Matrix(4,4);
    for(int i=0;i<16;i++)
    {
        m1[i]=i; //arbitrary values
        m2[i]=i+2;
    }
    m1.plainPrint();
    m2.plainPrint();
    m1=m2;
    m1.plainPrint();

}

这里是打印内容:

0 1 2 3 
4 5 6 7 
8 9 10 11 
12 13 14 15 

2 3 4 5 
6 7 8 9 
10 11 12 13 
14 15 16 17 

-nan 4.2039e-45 0 0 
-3.7918e-39 0 -1.19722e+16 4.2039e-45 
-nan 0 0 0 
-nan 0 0 0 

Process finished with exit code 0

请提供您的帮助!

我正在用c ++构建类“ Matrix”,并且在创建operator =时遇到了一些麻烦。下面提供了实现,然后是无效的代码,但让我澄清一下问题,...

c++ matrix operators variable-assignment
1个回答
0
投票

您可以这样做:

© www.soinside.com 2019 - 2024. All rights reserved.