I was trying to write a matrix class which would be able to find inverse,adjoint,etc. of a square matrix of any order.
The constructor initializes an identity matrix of order n(passed to it).
class Matrix
{
int** elements;
int order;
public:
Matrix& operator=(const Matrix& second_inp)
{
if(this->order!=second_inp.order)
cout<<"The matrix cannot be assigned!!!\n"<<this->order<<"\n"<<second_inp.order;
else
{
for(int i=0;i<this->order;i++)
for(int j=0;j<this->order;j++)
this->elements[i][j] = second_inp.elements[i][j];
}
return *this;
}
Matrix operator*(const Matrix& a)const
{
Matrix c(a.order);
for(int i=0;i<c.order;i++)
for(int j=0;j<c.order;j++)
c.elements[i][j]=0;
if (this->order!=a.order)
{
cout<<"The 2 Matrices cannot be multiplied!!!\n";
return Matrix();
}
else
{
for(int i=0;i<a.order;i++)
for(int j=0;j<a.order;j++)
for(int k=0;k<a.order;k++)
c.elements[i][j] += (this->elements[i][k])*(a.elements[k][j]);
return c;
}
}
};
~Matrix()
{
for(int i=0;i<this->order;i++)
delete[] *(elements+i);
delete[] elements;
elements=nullptr;
}
If i were to run the following code using this class:
Matrix exp1(2),exp2(2),exp3(2);
exp1.get_matrix();
exp3=exp1*exp2;
exp3.show_matrix();
I get a run-time error, while debugging i found out that, after the multiplication(exp1*exp2) the =operator was not able to access the data if the result of the *operator.
But if i were to use a manual destructor like this one at the end of the main() to free all allocated memory, the program works fine.
void destroctor()
{
for(int i=0;i<order;i++)
delete[] *(elements+i);
delete[] elements;
}
how can i edit the destructor or the operator overloads to correct this problem?
The constructor i used:
Matrix(int inp_order):order(inp_order)
{
elements=new int*[order];
for(int i=0;i<order;i++)
*(elements+i)=new int[order];
for(int i=0;i<order;i++)
for(int j=0;j<order;j++)
{
if (i==j)
*(*(elements+j)+i)=1;
else
*(*(elements+j)+i)=0;
}
}
It is hard to tell what is going wrong, since you have not posted your constructors.
In the exp3=exp1*exp2; a lot of things happen:
First a new matrix c is constructed in the operator* function. Then the return c; statement calls the copy constructor and then the destructor. After that operator= is called and after that the destructor for the temporary matrix again.
I think what happens is that you are using the default copy constructor which does not make a deep copy. That way the destructor being called at the time of return c deletes the data that still shared between the matrices.
I get a run-time error, while debugging i found out that, after the multiplication(exp1*exp2) the =operator was not able to access the data if the result of the *operator.
You didn't show us your constructor, so there is no way to tell why you are getting this errors.
I suspect that the cause is that you aren't allocating the memory needed to contain your matrix. You declared it as an int**, so you need to allocate an array of int* pointers, and for each of those you need to allocate an array of int.
Edit
While I was typing this you posted code for your constructor.
You are not returning a value from your overload of operator*, and you don't have a copy constructor (rule of three).
Do you have compiler warnings enabled? Any compiler worth its salt would have complained about the missing return statement in the operator overload.
You have not defined a copy constructor, so the compiler will generate one for you. This constructor will be called in order to copy the return value of operator*(const & Matrix a) into the result.
As the generated copy constructor only performs a shallow memberwise copy, it will not allocate a new array of elements, hence the error.
Related
This question already has answers here:
delete vs delete[] operators in C++
(7 answers)
Closed 2 years ago.
I'm trying to write a method to overload the * operator for multiplying matrices. the matrix it self has its data stored in a dynamically allocated array "_mat_arr" and after running a valgrind check i cant seem to free it properly after finishing with this method.
Matrix Matrix::operator* (const Matrix& rhs)
{
Matrix new_mat(this->_rows,rhs._cols);
/*...code to fill the product matrix...*/
return new_mat;
}
this is my destructor
~Matrix() /*destructor*/
{
delete [] _mat_arr;
_mat_arr = nullptr;
}
this is my class constructor where i allocate the matrix array
Matrix(int rows, int cols):_rows(rows),_cols(cols)
{
_mat_arr = new int [cols*rows];
for(int i = 0; i < rows * cols; i++)
{
_mat_arr[i] = 0;
}
_rowLen = _cols -1;
}
edit: changed delete to delete[].
after running the debugger i think that the problem is that the destructor is not called on new_mat which is allocated inside the method.
Your destructor does not use the correct delete. It should call the array version of delete, delete [].
You should also apply Rule of 3 here. Since you are allocating dynamic memory and defining a destructor, you should also define a copy constructor and a copy assignment operator.
Matrix(const Matrix& other);
Matrix& operator=(const Matrix& other);
I wrote a simple vector class which overloads assignment and addition operators. The code adds two vectors and prints vectors before and after the addition. Surprisingly destructor ~MyVector() is being called after the line c=a+b. I do not see the reason why is it so, as neither of objects a,b and c gets out of scope. Do you understand the reason for invocation of the destructor?
#include<iostream>
#include<cstdlib>
using namespace std;
template<typename T>
class MyVector
{
public:
MyVector(int s)
{
size=s;
a=new T[s];
}
~MyVector()
{
delete[] a;
size=0;
};
void freeVec()
{
cout<<"Calling destructor. a[0]= "<<a[0]<<endl;
if(a!=NULL)
{
free(a);
a=NULL;
}
}
int getSize(void)
{
return size;
}
void setSize(int ss)
{
size=ss;
}
T &operator[](int i)
{
return a[i];
}
MyVector &operator=(MyVector mv)
{
if(this==&mv)
return *this;
for(int i=0;i<mv.getSize();i++)
this->a[i]=mv[i];
this->size=mv.getSize();
return *this;
}
MyVector operator+(MyVector &mv)
{
for(int i=0;i<size;i++)
{
this->a[i]+=mv[i];
}
cout<<endl;
return *this;
}
private:
int size;
T *a;
};
int main(void)
{
MyVector<int> a(3),b(3),c(3);
a[0]=1;a[1]=2;a[2]=3;
b[0]=4;b[1]=5;b[2]=6;
cout<<"initial vector"<<endl;
for(int i=0;i<3;i++)
cout<<a[i]<<" ";
cout<<endl;
for(int i=0;i<3;i++)
cout<<b[i]<<" ";
cout<<endl;
c=a+b;
cout<<"final vectors"<<endl;
for(int i=0;i<3;i++)
cout<<a[i]<<" ";
cout<<endl;
for(int i=0;i<3;i++)
cout<<b[i]<<" ";
cout<<endl;
for(int i=0;i<3;i++)
cout<<c[i]<<" ";
cout<<endl;
cout<<endl;
return 0;
}
Your a + b returns a nameless temporary object that consequently gets copied to c (by the assignment operator) and then gets destructed. That's the destructor call that you see.
Also, your assignment operator receives it parameter by value (why???), which means that theoretically another copy can be created for that as well. Your compiler apparently optimized out that copy, which is why you see only one additional destructor call.
BTW, since you manually manage allocated memory in your object, it is a very good idea to implement copy constructor as well, in accordance with the "Rule of Three". The current version of the class (without copy constructor) can easily be used to build broken code specifically because the copy constructor is missing. In fact, your current code is already broken, since it uses compiler-provided copy constructor for copying your class object. The only reason you don't see any crashes is because the compiler optimized out (elided) most of the copies and, probably, because you got lucky.
On top of that your implementation of binary + modifies the data stored in *this object (why???), meaning that c = a + b modifies a. This is not exactly what people expect to see as a typical behavior of binary + operator.
There are lots of other bizarre things in your code. For example, what is freeVec and why is it trying to use free on memory that is always allocated by new[]? Also, why does the destructor set size to 0? What is the point of that?
Because your MyVector operator+(MyVector &mv) creates a copy (as it should do). This temporary copy is destroyed once it has been stored in c.
Note that modifying this in operastor+ is not a great plan. You don't expect a to become the same value as c from c = a + b;.
In the line c = a + b; there are actually 2 operations. The first is the addition. They way you have implemented it, a is actually incremented by the value of b. A copy of a is then returned in the line return *this;. This copy is not yet assigned to c; it is a nameless temporary.
In the assignment call, this copy is passed by value, thereby creating another copy. However, with copy elision, I believe it's possible the second copy is optimized out, so in total 1 copy is created. Thus the input to the assignment operator is a copy of an object. That object would get destroyed when the assignment operator returns.
Somewhat orthogonal to your question, I want to point out that there are a number of issues with the way you have implemented the operators. Firstly, your + operator is modifying the object that it is associated with. In the line c = a + b; the value of a gets modified because of the line this->a[i]+=mv[i]; in your function, which I believe is not your intended effect.
Secondly, in your implementation of the = operator, the lines
if(this==&mv)
return *this;
are useless because mv was passed by value and will never have the same address as this anyway.
Have problem with copy constructor and assignment operator. Have written code to multiply matricies:
Matrix& Matrix::operator * (const Matrix &second) const
{
// Create result matrix
Matrix result(Rows(), second.Columns());
// Multiply matricies
for (unsigned i = 0; i < Rows(); i++)
{
for (unsigned j = 0; j < second.Columns(); j++)
{
result[i][j] = 0.0;
for (unsigned k = 0; k < Columns(); k++)
{
result[i][j] += m_matrix[i][k] * second[k][j];
}
}
}
return result;
}
In Main code I call the operator:
Matrix C = A * B;
However code destroys result variable before assignment, how to write such code correctly to return result matrix? Copy constructor is:
Matrix::Matrix(const Matrix& matrix)
{
AllocateMatrixArray(matrix.Rows(), matrix.Columns());
CopyMatrixData(matrix);
}
Assignment operator is:
Matrix& Matrix::operator = (const Matrix& other)
{
AllocateMatrixArray(other.Rows(), other.Columns());
CopyMatrixData(other);
return *this;
}
However I see that compiler does not use it - copy constructor is enough.
Your code returns a reference to a local variable, which will be destroyed at the end of the function's scope. Don't do that:
Matrix Matrix::operator * (const Matrix &second) const {
// same as above
}
Note that the return value is now a Matrix instead of a Matrix&.
You should not be returning a reference to local variable. By convention the opertor*(I mean the two argument version of course) returns a copy to the result. Same holds true for the other operations like operator+, operator- and so on. A reference is returned by the moifying versions of those operators like operator *=, operator += and so on.
If you want to write expressions like C = A*B all C A and B must be "values".
So the return value of operator* must be matrix and not matrix&, espscialy if the & refers to a local variable (like result) thet will be destroyed at } (hence before = is executed).
That said, there are some more issues:
The sample Matrix C = A*B is not an assignment: an assignment happens the the value of an already existent object is changed. But Matrix C is created contextually: in fact, what it is called here, is the Matrix constructor (copy constructor, in this case)
There could be memory leaks: Although I don't see how the matrices data are handled, your operator=
seems to allocate new space and then copy the data in it. But what happens to the space containing the old data? Does it remain forgotten around? Is is automatically released by a smart pointer?
Similarly, just like = should dismiss the old data, also the class itself should dismiss its own data on destruction, hence a destructor should also be implemented. Otherwise every time a Matrix is dismissed (like the local result), its data will stay around.
I have a custom-made Matrix library for a neural network program and overloaded arithmetic operators.
Here's the class declarations:
class Matrix{
public:
int m;
int n;
double **mat;
Matrix(int,int);
Matrix(int);
Matrix(const Matrix& that):mat(that.mat),m(that.m),n(that.n)
{
mat = new double*[m];
for(int i = 0;i<m;i++)mat[i] = new double[n];
};
~Matrix();
friend istream& operator>>(istream &in, Matrix &c);
friend ostream& operator<<(ostream &out, Matrix &c);
Matrix operator+(const Matrix& other);
};
This is the function definition for + operation:
Matrix Matrix::operator+(const Matrix& other)
{
Matrix c(m,n);
for(int i=0;i<m;i++)
{
for(int j = 0; j<n;j++)
c.mat[i][j] = mat[i][j] + other.mat[i][j];
}
return c;
}
I have tried to implement it in all ways and error is same...here's an instance
Matrix x(m,n); //m and n are known
x = a+b; // a and b are also m by n matrices
I have debugged the code using breakpoints and here's the error...
The local matrix 'c' in operator function is destroyed before it is returned and hence what is assigned to x is a garbage pointer..
Please suggest me something...
You need to define a copy constructor for your class. The copy constructor will need to allocate memory for mat and make a copy of the data.
Without this, when you return c, a new object is constructed that has the same value of mat as c. When c subsequently goes out of scope, it deletes c.mat. As a result, the copy of c is left with a dangling pointer.
Having done this, you should also implement an assignment operator.
The value you returned is used to initialize a temporary, and this temporary is then copied into the result after the value you returned has been destroyed. This is normal behavior (unless the call is elided because of NRVO).
However, since your class has no explicitly defined copy constructor, the implicitly generated one will be invoked, and that will just copy a pointer (mat) to stuff that has been deallocated by the returned object's destructor.
This is a violation of the so-called Rule of Three, a programming best-practice saying that whenever your class explicitly defines a copy-constructor, an assignment operator, or a destructor, then it should define all of them. The rationale is that a class that defines one of them most likely does so because it is managing some resource, and for correctly handling resource releasing/acquiring logic, all of those three special member functions are needed.
Notice that in C++11 you can also have a move constructor that will be allowed to perform the transfer of the Matrix's content just by assigning pointers and invalidating the object you moved from.
Matrix(Matrix&& m)
{
mat = m.mat;
m.mat = nullptr;
}
Of course, if you introduce a move constructor, you will have to modify your class destructor accordingly to check if you really have to release the allocated memory:
~Matrix()
{
if (m.mat == nullptr)
{
return;
}
...
}
Your Matrix class has a raw pointer member and presumably allocates memory in its constructors, yet you have no copy constructor or copy assignment operator.
Also, you have a destructor, yet you have no copy constructor or copy assignment operator. This is a violation of the Rule of Three.
Your Matrix c is a local variable. So it is destroyed when that method where it was created ends. In C++ this unwanted situation is usually solved by copying objects. You can define copy constructor and assignment operator = with the same functionality. The problem of copying is that it is slow, so if you want it to be faster, you should use a different approach withotu copying. For example, you can add a parameter to the method where caller would pass a reference to the existing matrix object where to store the result.
You need a copy constructor and an assignment operator for your class that make a deep copy of the object as the compiler generated functions will not.
The compiler generated copy constructors and assignment operators will simply copy the objects contained in the class. In your case these are PODs, so the automatically generated functions will simply do a bitwise copy. In the case of the double**, this will result in the copy of the pointer value, not the pointed to values. As a result, you end up with two Matrix objects pointing to the same underlying data, just before the destructor pulls the rug out from underneath you.
You should change your code to return a Matrix *, rather than a Matrix object. This way you can ensure that the Matrix object lives after the function. (Your current code makes the Matrix object a function variable, thus it will be removed after the function has ended).
Your code could look like this:
Matrix *Matrix::operator+(const Matrix& other)
{
Matrix *c = new Matrix(m,n);
for(int i=0;i<m;i++)
{
for(int j = 0; j<n;j++)
c->mat[i][j] = mat[i][j] + other.mat[i][j];
}
return c;
}
EDIT: Apparently this is bad practice, guess I also learned something today :)
Here is an example of a class that is made available for the + operation.
class A
{
public:
int *array;
A()
{
array = new int[10];
}
~A()
{
delete[] array;
}
A operator+ (const A &b)
{
A c;
for(int i=0; i<10; i++)
c.array[i] += array[i] + b.array[i];
return c;
}
};
int main()
{
A a,b,c,d;
/* puts some random numbers into the arrays of b,c and d */
a = b+c+d;
}
Will a run the destructor before copying the result of b+c+d or not? If not, how do I make sure no memory is leaked?
The + operator overload is designed this way such that no operand is modified.
You need to add an equals operator to A. Also, you will likely want to create a copy constructor.
When a becomes the return from b+c+d, the array pointer in a gets over written without delete[] ever being called on it. You need to make an operator= that deletes the array.
An example of an operator= is below:
A& operator=(A const& a)
{
if (&a != this) {
int* tmp = this->array;
this->array = new int[10];
//copy a.array to this->array
delete[] tmp;
}
return *this;
}
There's a lot of subtleties in this if you're new to operator=.
In particular, the check whether or not a is equal to this is necessary because it's perfectly valid to write:
A a;
a = a;
This would cause a pointless copy, and in most cases of operator= will cause bugs.
The other subtlety is less of a requirement than that one and more of a coding style (though a very wide spread standard). When copying something that is dynamically allocated, you always want to allocate and copy before you release. That way, if new throws an exception (or something else fails), the object is still in a stable state, though with it's old data instead of the new expected dated.
Will this cause memory leak?
Yes, it will. You forgot to add copy constructor and assignment operator. See Rule of Three
You could also use std::vector<int> for A::array instead of int*. In this case you wouldn't need to worry about copy constructor/assignment operator (as long as you don't add something else that must be handled in destrcutor).