I am sort of new to c++ and wanted to write a small matrix library which has a base class Matrix
from which some new matrix types like SparseMatrix
, DenseMatrix
, HashMatrix
etc.
My base class looks like this:
class Matrix {
protected:
int m,n;
public:
Matrix(int m_p, int n_p) : m(m_p), n(n_p){
std::cout << "gen constr" << std::endl;
}
Matrix(Matrix& other) = delete;
Matrix() = delete;
virtual ~Matrix() {}
int getM() const {
return m;
}
int getN() const {
return n;
}
virtual double& get(int m, int n) = 0;
virtual double get(int m, int n) const = 0;
inline double& operator() (int m, int n){
return get(m,n);
}
inline double operator() (int m, int n) const{
return get(m,n);
}
friend std::ostream &operator<<(std::ostream &os, Matrix &matrix) {
using std::scientific;
using std::fixed;
os << std::fixed << std::setprecision(2) << scientific << std::setfill(' ');
for(int i = 1; i <= matrix.getM(); i++){
for(int j = 1; j <= matrix.getN(); j++){
os << std::setw(10) << matrix.get(i,j) << " ";
}
os << "\n";
}
return os;
}
Matrix& operator=(const Matrix& other) {
// std::cout << "equality assign" << std::endl;
return *this;
}
};
As you can see, I have overwritten the equality assign operator which simply returns the object and does not actually copy values.
My first implementation of DenseMatrix
is very straight forward:
class DenseMatrix : public Matrix{
private:
double* data;
public:
DenseMatrix(int mP, int nP) : Matrix(mP, nP){
std::cout << "gen constr base" << std::endl;
this->data = new double[mP * nP]{0};
}
DenseMatrix() = delete;
~DenseMatrix() {
delete this->data ;
}
double &get(int m, int n) {
int index = m*getN()+n-(getN()+1);
assert(index < (getN() * getM()) && index >= 0);
return this->data [index];
}
double get(int m, int n)const {
int index = m*getN()+n-(getN()+1);
assert(index < (getN() * getM()) && index >= 0);
return this->data [index];
}
};
Furthermore the main()
function looks like this:
DenseMatrix mat(3,3);
for(int i = 1; i<= 3; i++){
mat(i,i) = i;
}
DenseMatrix mat2(3,3);
mat2 = mat;
std::cout << mat << std::endl;
std::cout << mat2 << std::endl;
>>> 1.00e+00 0.00e+00 0.00e+00
>>> 0.00e+00 2.00e+00 0.00e+00
>>> 0.00e+00 0.00e+00 3.00e+00
>>> 1.00e+00 0.00e+00 0.00e+00
>>> 0.00e+00 2.00e+00 0.00e+00
>>> 0.00e+00 0.00e+00 3.00e+00
As you can see, I create two matrices first. I adjust the values for the first matrix and leave the values of the second matrix default to 0. Yet after calling the equality assign operator, the content of the second matrix changes even tho the function I implemented has basically no code which affects the matrix.
I do not understand this behavior and would be very happy if someone could briefly explain what is going on here.
Thank you very much for your patience and help :)
You have not deleted or defined the operator=
copy-assignment operator for DenseMatrix
, so the compiler will synthesize one for you. This function is going to do a member wise copy of the data members, in this case double *data
. Since the pointer is going to point to the same contents in both mat
and mat2
, you see the same contents when you print them out.
Note that this is probably not what you want. One issue is that your DenseMatrix
destructor is going to delete
data
twice, leading to possibly a segfault.