I'm learning C++ and trying to write a C++ class for matrices, where I store the matrix as a one-dimensional C array. To this end, I defined an element member function to access the matrix elements based on their location in the array. I have then overloaded the << and + operators to handle the display and addition of matrices. The << operator works as intended, as can be demonstrated in the following example:
#include<iostream>
class matrix {
friend std::ostream & operator<<(std::ostream &os, matrix &M);
private:
int rows{}, columns{};
double *array {nullptr};
public:
matrix(int rows, int columns);
~matrix() {}
double & element(int r, int c);
matrix operator+(matrix &M)
{
matrix N(rows, columns);
if (M.rows!=rows || M.columns!=columns){
std::cout << "ERROR: DIMENSIONS OF MATRICES DO NOT MATCH" << std::endl;
}
else{
for (int i{1}; i<=M.rows; i++)
for (int j{1}; j<=M.columns; j++){
N.element(i,j) = element(i,j) + M.element(i,j);
}
}
return N;
}
};
matrix::matrix(int r, int c)
{
rows = r;
columns = c;
array = new double[rows*columns];
for(int i{0}; i<rows*columns; i++) array[i]=0.0;
}
double & matrix::element(int i, int j)
{
int loc{0};
loc = (j-1) + (i-1)*columns;
return array[loc];
}
std::ostream & operator<<(std::ostream &os, matrix &M)
{
for (int i{1}; i<=M.rows; i++){
os << "[ ";
for (int j{1}; j<=M.columns; j++){
os << M.element(i,j) << " ";
}
os << "] \n";
}
return os;
}
int main() {
matrix A(2,2);
matrix B(2,2);
A.element(1,1) = 1;
A.element(1,2) = 2;
A.element(2,1) = 3;
A.element(2,2) = 4;
B.element(1,1) = 1;
B.element(1,2) = 2;
B.element(2,1) = 3;
B.element(2,2) = 4;
std::cout << A << std::endl;
std::cout << B << std::endl;
return 0;
}
I'm then unable to display the addition of two matrices:
std::cout << A+B << std::endl;
If I, however, break up the operation and add the matrices separately before displaying their sum, I get the right output, which makes me believe that the + operator also works correctly:
matrix C(2,2);
C = A+B;
std::cout << C << std::endl;
The error seems to suggest that there may be an issue converting the matrix elements into the ostream, but it's curious that the above workaround solution works.
Your << operator takes a non-const reference to a matrix as parameter. That means it can't take reference to a temporary object.
The result of A+B is a temporary object if you don't assign it to something.
So you need to change this:
std::ostream & operator<<(std::ostream &os, matrix &M);
into this:
std::ostream & operator<<(std::ostream &os, const matrix &M);
You may sooner or later encounter the same problem with your +-operator:
matrix operator+(matrix &M)
should be
// Both `M` and `*this` should be const
matrix operator+(const matrix &M) const
Naturally you will then have a problem with your element method which can only act on a non-const object, so you also need a variant that acts on a const object:
class matrix
{
....
public:
double & element(int r, int c);
double element(int r, int c) const;
...
}
You can't take a non-const reference of a temporary object. You're trying to call operator<< with a temporary (A+B) but the signature of your overloaded operator<< takes a non-const reference so your function isn't a valid candidate.
To fix this you'll need to change a couple things. First, make your overloaded << operator take a const reference to the matrix. And don't forget to fix the friend signature in the class declaration.
std::ostream & operator<<(std::ostream &os, const matrix &M);
Just doing that will still cause errors because the element method is only defined for non-const objects. You'll need to add an overload for element that acts on const matrixes (and that won't let you modify the returned element).
double matrix::element(int i, int j) const
{
int loc = (j-1) + (i-1)*columns;
return array[loc];
}
Your operator<< and operator+ both need to take the input matrix by const reference, so that they can accept temporary matrix objects as input.
Also, operator+ should be const-qualified since it doesn't modify the contents of this. And element() should have a const -qualified overload so it can provide read-only access to a const matrix object.
You are also missing a copy constructor, a copy-assignment operator, a move constructor, and a move-assignment operator, per the Rule of 3/5/0. And also, your destructor is not freeing the C array at all, so it is being leaked.
Try this instead:
#include <iostream>
#include <stdexcept>
#include <utility>
class matrix {
friend std::ostream& operator<<(std::ostream &os, const matrix &M);
private:
int rows{}, columns{};
double* array{nullptr};
public:
matrix(int rows, int columns);
matrix(const matrix &M);
matrix(matrix &&M);
~matrix();
matrix& operator=(matrix M);
double& element(int r, int c);
double element(int r, int c) const;
matrix operator+(const matrix &M) const;
matrix& operator+=(const matrix &M);
};
matrix::matrix(int r, int c)
: rows(r), columns(c)
{
size_t size = rows*columns;
array = new double[size];
for(size_t i = 0; i < size; ++i)
array[i] = 0.0;
}
matrix::matrix(const matrix &M)
: rows(M.rows), columns(M.columns)
{
size_t size = rows*columns;
array = new double[size];
for(size_t i = 0; i < size; ++i)
array[i] = M.array[i];
}
matrix::matrix(matrix &&M)
: rows(M.rows), columns(M.columns), array(M.array)
{
M.rows = M.columns = 0;
M.array = nullptr;
}
matrix::~matrix()
{
delete[] array;
}
matrix& operator=(matrix M)
{
std::swap(rows, M.rows);
std::swap(columns, M.columns);
std::swap(array, M.array);
return *this;
}
double& matrix::element(int r, int c)
{
// TODO: do bounds checking here...
size_t loc = ((r-1)*columns) + (c-1);
return array[loc];
}
double matrix::element(int r, int c) const
{
// TODO: do bounds checking here...
size_t loc = ((r-1)*columns) + (c-1);
return array[loc];
}
std::ostream & operator<<(std::ostream &os, const matrix &M)
{
for (int r = 1; r <= M.rows; ++r){
os << "[ ";
for (int c = 1; c <= M.columns; ++c){
os << M.element(r,c) << " ";
}
os << "]\n";
}
/* alternatively...
size_t loc = 0;
for (int r = 0; r < M.rows; ++r){
os << "[ ";
for (int c = 0; c < M.columns; ++c){
os << M.array[loc++] << " ";
}
os << "]\n";
}
*/
return os;
}
matrix matrix::operator+(const matrix &M) const
{
matrix N(*this);
N += M;
return N;
}
matrix& matrix::operator+=(const matrix &M)
{
if (M.rows != rows || M.columns != columns){
throw std::runtime_error("DIMENSIONS OF MATRICES DO NOT MATCH");
}
for (int r = 1; r <= rows; ++r)
for (int c = 1; c <= columns; ++c){
element(r,c) += M.element(r,c);
}
}
/* alternatively:
size_t size = rows*columns;
for (size_t i = 0; i < size; ++i)
array[i] += M.array[i];
}
*/
return *this;
}
int main() {
matrix A(2,2);
matrix B(2,2);
A.element(1,1) = 1;
A.element(1,2) = 2;
A.element(2,1) = 3;
A.element(2,2) = 4;
B.element(1,1) = 1;
B.element(1,2) = 2;
B.element(2,1) = 3;
B.element(2,2) = 4;
std::cout << A << std::endl;
std::cout << B << std::endl;
return 0;
}
Related
The issue I am having is how to get the correct number columns to go through for the inner most loop of K.
An example is a 2x3 matrix and a 3x2 matrix being multiplied.
The result should be a 2x2 matrix, but currently I dont know how to send the value of 2 to the operator overloaded function.
It should be
int k = 0; k < columns of first matrix;k++
Matrix::Matrix(int row, int col)
{
rows = row;
cols = col;
cx = (float**)malloc(rows * sizeof(float*)); //initialize pointer to pointer matrix
for (int i = 0; i < rows; i++)
*(cx + i) = (float*)malloc(cols * sizeof(float));
}
Matrix Matrix::operator * (Matrix dx)
{
Matrix mult(rows, cols);
for (int i = 0; i < rows; i++)
{
for (int j = 0; j < cols; j++)
{
mult.cx[i][j] = 0;
for (int k = 0; k < ?;k++) //?????????????
{
mult.cx[i][j] += cx[i][k] * dx.cx[k][j];
}
}
}
mult.print();
return mult;
//calling
Matrix mult(rowA, colB);
mult = mat1 * mat2;
}
Linear algebra rules say the result should have dimensions rows x dx.cols
Matrix Matrix::operator * (Matrix dx)
{
Matrix mult(rows, dx.cols);
for (int i = 0; i < rows; i++)
{
for (int j = 0; j < cols; j++)
{
mult.cx[i][j] = 0;
for (int k = 0; k < cols;k++) //?????????????
{
mult.cx[i][j] += cx[i][k] * dx.cx[k][j];
}
}
}
mult.print();
return mult;
A few random hints:
Your code is basically C; it doesn’t use (e.g.) important memory-safety features from C++. (Operator overloading is the only C++-like feature in use.) I suggest that you take advantage of C++ a bit more.
Strictly avoid malloc() in C++. Use std::make_unique(...) or, if there is no other way, a raw new operator. (BTW, there is always another way.) In the latter case, make sure there is a destructor with a delete or delete[]. The use of malloc() in your snippet smells like a memory leak.
What can be const should be const. Initialize as many class members as possible in the constructor’s initializer list and make them const if appropriate. (For example, Matrix dimensions don’t change and should be const.)
When writing a container-like class (which a Matrix may be, in a sense), don’t restrict it to a single data type; your future self will thank you. (What if you need a double instead of a float? Is it going to be a one-liner edit or an all-nighter spent searching where a forgotten float eats away your precision?)
Here’s a quick and dirty runnable example showing matrix multiplication:
#include <cstddef>
#include <iomanip>
#include <iostream>
#include <memory>
namespace matrix {
using std::size_t;
template<typename Element>
class Matrix {
class Accessor {
public:
Accessor(const Matrix& mat, size_t m) : data_(&mat.data_[m * mat.n_]) {}
Element& operator [](size_t n) { return data_[n]; }
const Element& operator [](size_t n) const { return data_[n]; }
private:
Element *const data_;
};
public:
Matrix(size_t m, size_t n) : m_(m), n_(n),
data_(std::make_unique<Element[]>(m * n)) {}
Matrix(Matrix &&rv) : m_(rv.m_), n_(rv.n_), data_(std::move(rv.data_)) {}
Matrix operator *(const Matrix& right) {
Matrix result(m_, right.n_);
for (size_t i = 0; i < m_; ++i)
for (size_t j = 0; j < right.n_; ++j) {
result[i][j] = Element{};
for (size_t k = 0; k < n_; ++k) result[i][j] +=
(*this)[i][k] * right[k][j];
}
return result;
}
Accessor operator [](size_t m) { return Accessor(*this, m); }
const Accessor operator [](size_t m) const { return Accessor(*this, m); }
size_t m() const { return m_; }
size_t n() const { return n_; }
private:
const size_t m_;
const size_t n_;
std::unique_ptr<Element[]> data_;
};
template<typename Element>
std::ostream& operator <<(std::ostream &out, const Matrix<Element> &mat) {
for (size_t i = 0; i < mat.m(); ++i) {
for (size_t j = 0; j < mat.n(); ++j) out << std::setw(4) << mat[i][j];
out << std::endl;
}
return out;
}
} // namespace matrix
int main() {
matrix::Matrix<int> m22{2, 2};
m22[0][0] = 0; // TODO: std::initializer_list
m22[0][1] = 1;
m22[1][0] = 2;
m22[1][1] = 3;
matrix::Matrix<int> m23{2, 3};
m23[0][0] = 0; // TODO: std::initializer_list
m23[0][1] = 1;
m23[0][2] = 2;
m23[1][0] = 3;
m23[1][1] = 4;
m23[1][2] = 5;
matrix::Matrix<int> m32{3, 2};
m32[0][0] = 5; // TODO: std::initializer_list
m32[0][1] = 4;
m32[1][0] = 3;
m32[1][1] = 2;
m32[2][0] = 1;
m32[2][1] = 0;
std::cout << "Original:\n\n";
std::cout << m22 << std::endl << m23 << std::endl << m32 << std::endl;
std::cout << "Multiplied:\n\n";
std::cout << m22 * m22 << std::endl
<< m22 * m23 << std::endl
<< m32 * m22 << std::endl
<< m23 * m32 << std::endl
<< m32 * m23 << std::endl;
}
Possible improvements and other recommendations:
Add consistency checks. throw, for example, a std::invalid_argument when dimensions don’t match on multiplication, i.e. when m_ != right.n_, and a std::range_error when the operator [] gets an out-of-bounds argument. (The checks may be optional, activated (e.g.) for debugging using an if constexpr.)
Use a std::initializer_list or the like for initialization, so that you can have (e.g.) a const Matrix initialized in-line.
Always check your code using valgrind. (Tip: Buliding with -g lets valgrind print also the line numbers where something wrong happened (or where a relevant preceding (de)allocation had happened).)
The code could me made shorter and more elegant (not necessarily more efficient; compiler optimizations are magic nowadays) by not using operator [] everywhere and having some fun with pointer arithmetics instead.
Make the type system better, so that (e.g.) Matrix instances with different types can play well with each other. Perhaps a Matrix<int> multiplied by a Matrix<double> could yield a Matrix<double> etc. One could also support multiplication between a scalar value and a Matrix. Or between a Matrix and a std::array, std::vector etc.
i have this class
class Matrix
{
int size;
std::unique_ptr<std::unique_ptr<int[]>[]> val;
public:
Matrix(int size1)
{
size=size1;
val=std::make_unique< std::unique_ptr<int[]>[] >(size);
...
}
... move constructor,move assignment operator
Matrix& operator+(Matrix &m)
{
Matrix sumMatrix(size);
for ( int i = 0; i < size; ++i)
{
for (int j = 0; j < size; ++j){
sumMatrix.val[i][j]=this->val[i][j]+m.val[i][j];
}
}
return sumMatrix;
}
and main :
...
Matrix e=b+c;
std::cout<<"e="<<std::endl;
e.print();
and i have this error :
warning: reference to local variable 'sumMatrix' returned
[-Wreturn-local-addr]
Matrix sumMatrix(size);
Can someone please help me with this ??
Return by value, as you should for operator+ most of the time:
// vvv--Removed & vvvvv-----vvvvv--Const is more appropriate here
Matrix operator+(Matrix const &m) const { ... }
This will require a copy constructor, make sure to add that. Also note that you should probably collect your for-loop logic into an operator+= and simplify operator+ significantly while providing more functionality for the end-user:
Matrix& operator+=(Matrix const& m) {
for (int i = 0; i < size; ++i) {
for (int j = 0; j < size; ++j) {
//vvv--No need for this-> in C++
val[i][j] += m.val[i][j];
}
}
return *this;
}
Matrix operator+(Matrix const& m) const {
Matrix sumMatrix{m}; // requires a copy constructor.
sumMatrix += *this;
return sumMatrix;
}
why am I having an error on the operator '[]'. I wanted to print the contents of my matrix. If i can't use the brackets, what could i do then?
here's a sample of the code:
#include <iostream>
#include <vector>
template <typename T>
class Matrix {
private:
int m; int n;
std::vector<T> x;
std::vector<std::vector<int>> Mat;
public:
Matrix (const unsigned int &m, const unsigned int &n, std::vector<T> x);
Matrix(const Matrix &M);
Matrix<T> operator = (const Matrix &M);
// Matrix<T> operator [](const int &index);
friend std::ostream& operator << (std::ostream& os, const Matrix<T> &M) {
os << "[";
for (int i = 0; i< M.m; i++){
for (int j = 0; j< M.n; j++){
os << M[i][j] << ' ';
}
os << '\n';
}
os << "]\n";
return os;
}
};
I have fixed the errors. But it doesn't print my matrix.
This is my main:
int main(){
std::vector<int> x = {1,2,3,4};
Matrix<int> A{2,2,x};
Matrix<int> B{2,2,x};
std::cout << A;
std::cout << B;
return 0;
}
And this is my constructor, I needed to make a matrix from a vector where I specify the rows and columns.
template <typename T>
Matrix<T>::Matrix (const unsigned int &m, const unsigned int &n, std::vector<T> x){ //constructor
this -> m = m;
this -> n = n;
this -> x = x;
int index = 0;
for (int i = 0; i<m; i++){
for (int j = 0; j<n; j++){
Mat[i][j] = x[index];
index++;
}
}
}
The issue is this line:
os << M[i][j] << ' ';
Because M is of type Matrix<T> and you haven't defined [] operator, any attempts to use [] operator will give you error.
Instead, You should use data member Mat.
friend std::ostream& operator << (std::ostream& os, const Matrix<T> &M) {
os << "[";
for (int i = 0; i< M.m; i++){
for (int j = 0; j< M.n; j++){
os << M.Mat[i][j] << ' '; // using M.Mat instead of M
}
os << '\n';
}
os << "]\n";
return os;
}
Edit:
As per your updated code, you may get a nice SIGSEGV error (Segmentation Fault) issue. Why? Simple. You are not resizing your data member Mat.
You have to do this:
template <typename T>
Matrix<T>::Matrix (const unsigned int &m, const unsigned int &n, std::vector<T> x){ //constructor
this -> m = m;
this -> n = n;
this -> x = x;
int index = 0;
// resizing Matrix according to our need i.e. m rows and n columns
Mat.resize(m);
for (unsigned int i = 0; i < Mat.size(); i++) {
Mat[i].resize(n);
}
for (unsigned int i = 0; i<m; i++){
for (unsigned int j = 0; j<n; j++){
Mat[i][j] = x[index];
index++;
}
}
}
You have different mistakes in your code:
1.- Your constructor:
Matrix<T>::Matrix (const unsigned int &m, const unsigned int &n, std::vector<T> x)
it's not a good idea to pass a vector by value, its always better to pass it by reference, and never pass an integer by const reference, pass it by value:
Matrix<T>::Matrix (unsigned int m, unsigned int n, const std::vector<T>& x)
2.- This is not an error, but you don't usually need to use "this->", and its better to construct an object like:
Matrix<T>::Matrix (unsigned int m0, unsigned int n0, const std::vector<T>& x0)
: m{m0}, n{n0}, x{x0} {...}
3.- I don't understand why you make 2 copys of the same elements: one in your vector x, and other with M. Your wasting your memory. Maybe with x is enough?
4.- You define m and n as signed int, but in your constructor you use "unsigned" int. Which one do you want to use?
I propose this changes:
1.- If you want to access to an element (i,j), write the operator:
Matrix& operator()(unsigned int i, unsigned int j);
its easy using your vector x.
2.- To write all the elements you can write something like:
std::ostream& operator << (std::ostream& os, const Matrix<T>& M) {
os << "[";
for (int i = 0; i< M.rows(); ++i){
for (int j = 0; j< M.cols(); ++j){
os << M(i, j) << ' ';
}
os << '\n';
}
os << "]\n";
return os;
}
and this is not a friend function (if you define rows() and cols()).
your operator[] returns a Matrix. You should change it to your template value.
CPP
#include "del2.h"
Matrix::Matrix()
{
dArray = NULL;
}
bool Matrix::isValid() const
{
if (dArray == NULL)
return false;
return true;
}
Matrix::~Matrix()
{
delete [] dArray;
}
Matrix::Matrix(unsigned int nRows)
{
rows = nRows;
columns = nRows;
dArray = new double[nRows * nRows];
for (unsigned int i = 0; i < nRows; i++)
{
for (unsigned int n = 0; n < nRows; n++)
{
at(i,n) = 0;
}
}
at(0,0) = 1;
at(rows-1,columns-1) = 1;
}
Matrix::Matrix(unsigned int nRows, unsigned int nColumns)
{
dArray = new double[nRows * nColumns];
rows = nRows;
columns = nColumns;
for (unsigned int i = 0; i < nRows; i++)
for (unsigned int n = 0; n < nColumns; n++)
dArray[i * columns + n] = 0;
}
const Matrix Matrix::operator =(const Matrix & rhs)
{
columns = rhs.getColumns();
rows = rhs.getRows();
delete [] dArray;
dArray = new double[rows * columns];
for (int row = 0; row < rows; row++)
for (int column = 0; column < columns; column++)
at(row,column) = rhs.at(row,column);
return *this;
}
std::ostream & operator <<( std::ostream & out, const Matrix & classPrint )
{
if (!classPrint.isValid())
return out;
int rows = classPrint.getRows();
int columns = classPrint.getColumns();
out << std::endl;
for (int i = 0; i < rows; i++)
{
out << "| ";
for (int n = 0; n < columns; n++)
out << classPrint.at(i,n) << " ";
out << "|" << std::endl;
}
out << endl;
return out;
}
HEADER:
#ifndef DEL2
#define DEL2
#include <iostream>
using namespace std;
class Matrix
{
private:
int rows;
int columns;
double * dArray;
public:
~Matrix();
Matrix();
explicit Matrix(unsigned int nRows);
Matrix(unsigned int nRows, unsigned int nColumns);
const Matrix operator =(const Matrix & rhs);
const double at(int row, int column) const
{ return dArray[ row*this->columns + column ]; }
double & at( int row, int column )
{ return dArray[ row*this->columns + column ]; }
const int getRows() const {return rows;}
const int getColumns() const {return columns;}
bool isValid() const;
};
std::ostream & operator <<( std::ostream & out, const Matrix & classPrint );
#endif // MATRIX
Main:
#include <iostream>
#include "del2.h"
using namespace std;
int main()
{
Matrix A;
Matrix B(10);
A = B;
cout << A;
return 0;
}
When I run this, the following happens:
The first index, matrix[0] of A, always becomes some weird number like 2.22323e-306. I don't understand why. Even when I try to set "at(0,0) = 1;" in the operator = - function after the loop, it still doesn't have 0.
The problem is here
const Matrix operator =(const Matrix & rhs);
should be
const Matrix& operator =(const Matrix & rhs);
and the definition should be
const Matrix& Matrix::operator =(const Matrix & rhs)
{
if (&rhs == this)
return *this;
Otherwwise operator= is returning a copy of the Matrix which will have dArray same as the original Matrix. Your data will be deleted when the temporary returned array goes out of scope.
Be carefull the operator = is not correct
Matrix & operator = (const Matrix & rhs){
if (&rhs != this){
// Your stuff here
}
return *this;
}
Calling delete [] on a null array is undefined. It can crash.
You must also define the copy constructor
I have a class project that is to make and operate on dynamic objects.
I have a class called Matrix that uses a 2 dimensional pointer array to store object of type Complex (which is a complex number class). I need to be able to add 2 arrays by adding all of the values in the arrays together and returning a new array. The issue is that I don't understand the syntax for accessing each Complex object in the array. Here is what I have so far for the overloaded addition operator:
const Matrix Matrix::operator+(const Matrix& rhs) const
{
Matrix newMatrix(mRows,mCols);
for(int i=0;i<mRows;i++)
{
for(int j=0;j<mCols;j++)
{
(*newMatrix.complexArray[i]) = (*complexArray[i])+ (*rhs.complexArray[i]);
}
}
return newMatrix;
}
Here is the overloaded input operator for the Matrix object:
istream& operator>>(istream& input, Matrix& matrix)
{
bool inputCheck = false;
int cols;
while(inputCheck == false)
{
cout << "Input Matrix: Enter # rows and # columns:" << endl;
input >> matrix.mRows >> cols;
matrix.mCols = cols/2;
//checking for invalid input
if(matrix.mRows <= 0 || cols <= 0)
{
cout << "Input was invalid. Try using integers." << endl;
inputCheck = false;
}
else
{
inputCheck = true;
}
input.clear();
input.ignore(80, '\n');
}
if(inputCheck = true)
{
cout << "Input the matrix:" << endl;
for(int i=0;i< (matrix.mRows+matrix.mCols);i++)
{
Complex* newComplex = new Complex();
input >> *newComplex;
matrix.complexArray[i] = newComplex;
}
}
return input;
}
Here is the Matrix class definition:
class Matrix
{
friend istream& operator>>(istream&, Matrix&);
friend ostream& operator<<(ostream&, const Matrix&);
private:
int mRows;
int mCols;
static const int MAX_ROWS = 10;
static const int MAX_COLUMNS = 15;
Complex **complexArray;
public:
Matrix(int=0,int=0);
Matrix(Complex&);
~Matrix();
Matrix(Matrix&);
Matrix& operator=(const Matrix&);
const Matrix operator+(const Matrix&) const;
};
And the constructor:
Matrix::Matrix(int r, int c)
{
if(r>0 && c>0)
{
mRows = r;
mCols = c;
}
else
{
mRows = 0;
mCols = 0;
}
if(mRows < MAX_ROWS && mCols < MAX_COLUMNS)
{
//complexArray= new Complex[mRows];
complexArray= new Complex*[mRows];
for(int i=0;i<mRows;i++)
{
complexArray[i] = new Complex[mCols];
}
}
}
As it is now, the program compiles, but stops working when it gets to the addition of matrices during runtime. If anyone can tell me what syntax I should be using and why, it would be extremely helpful.
You don't seem to be taking in enough input. You're taking (rows+cols) complex numbers as input but then attempting (correctly) to iterate over (rows*cols) elements within the matrix.
for(int i=0;i< (matrix.mRows+matrix.mCols);i++)
versus
for(int i=0;i<mRows;i++)
{
for(int j=0;j<mCols;j++)