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 :)
Related
Upon testing my C++11 code I encountered a bug whose origin is unclear to me. I have managed to reproduce the bug in the following contrived program.
#include <iostream>
class Vector {
public:
double* data;
Vector(int n) {data = new double[n];};
~Vector() {delete[] data;}
};
Vector someMethod() {
if (true) {
Vector mat {3};
if (true) {
mat.data[0] = 0.1;
mat.data[1] = 0.2;
mat.data[2] = 0.3;
}
return mat;
}
}
int main() {
Vector mat { someMethod() };
std::cout << mat.data[0] << std::endl;
std::cout << mat.data[1] << std::endl;
std::cout << mat.data[2] << std::endl;
return 0;
}
The following output is produced by the program:
0
0.2
0.3
*** Error in `./testy': double free or corruption (fasttop): 0x0000000001f75010 ***
Aborted (core dumped)
Whereas the output should be:
0.1
0.2
0.3
It appears that the first value is corrupted. I experimented with different Vector lengths, it is always the case that only the first value is corrupted. I have failed to come up with a satisfactory explanation to the above behavior. I suspect it is due to the fact that the Vector object is declared and initialized in the block scope of an if() statement which is in the block scope of someMethod(). However I do not understand why that should be a problem, if indeed it is.
EDIT
Both solutions presented, the first following the rule of 3/5 and the second following the rule of 0, worked. Thank you! However I am still puzzled as to why this behavior occurs. What mechanism causes the the value to be corrupted? When I invoke the default move constructor in defining the Vector object at the start of the main method, what in its default implementation causes this behavior?
someMethod produces Vector mat. This Vector is copied to the Vector mat inside main. Since you didn't specify a copy constructor the compiler gives you the default copy constructor, which just copies every element that Vector has, which is double * data. After the copy both Vectors have a pointer to the same data. Then the original mat inside someMethod is destroyed, meaning its destructor runs, which deletes the data of both vectors. Once someMethod returns you get a Vector mat with an invalid data pointer. You then print out the invalid memory, causing undefined behavior. In this particular case the undefined behavior decided to give you slightly wrong output, but it could just as easily caues a segmentation fault.
I hope now it is clear why the fix from zenith corrects the issue.
You need to follow the rule of three/five/zero, which says
If a class requires a user-defined destructor, a user-defined copy constructor, or a user-defined copy assignment operator, it almost certainly requires all three.
In C++11, it's five instead of three because of the addition of the move constructor and move assignment operator.
So your class should look like this with the addition of appropriate copy constructor and assignment operator:
class Vector {
public:
double* data;
Vector(int n) {data = new double[n];}
// copy constructor
Vector(Vector const& source) {
data = new double[ /* the same `n` as used in to allocate *source.data */ ];
// copy *data from `source` to this->data
}
// copy assignment operator
Vector& operator=(Vector const& source) {
delete[] data;
data = new double[ /* the same `n` as used in to allocate *source.data */ ];
// copy *data from `source` to this->data
return *this;
}
~Vector() {delete[] data;}
};
You can add move operators to make it more efficient if you want.
To summarize the rule of zero:
Classes that have custom destructors, copy/move constructors or copy/move assignment operators should deal exclusively with ownership (which follows from the Single Responsibility Principle). Other classes should not have custom destructors, copy/move constructors or copy/move assignment operators.
It would look like this:
#include <memory>
class Vector {
public:
std::unique_ptr<double[]> data;
Vector(int n) {data.reset(new double[n]);}
// no need to implement move constructor and move assignment operator,
// the automatically generated ones do the Right Thing because
// the resource is managed by the unique_ptr
// copy constructor and copy assignment operator are deleted
// because unique_ptr enforces the uniqueness of its managed
// resource
// if we wanted, we could implement the copy operators to do
// a deep copy of `data`, then we would just need to declare
// the move operators `= default` to not have them deleted.
// no need for destructor: unique_ptr manages the resource
};
I have the following simple vector class, where I can define vectors of different sizes and sum them; I have overloaded the + operator and include a simple data display method desplegar(); the class is defined as:
class Cvector{
private:
int dim;
float * C;
public:
Cvector(){};
Cvector(int n){dim=n; C = new float[dim];};
~Cvector(){delete [] C;};
int getdim(){return dim;};
float getC(int i){
if(i<dim && i>=0)
return C[i];
else
return 0;
};
void setC(int i, float x){
if(i<dim && i>=0)
C[i]=x;
}
void desplegar(){
cout<<"[ ";
for(int i=0;i<dim;i++)
cout<<getC(i)<<" ";
cout<<" ]"<<endl;
}
Cvector operator + (Cvector);
};
Cvector Cvector::operator + (Cvector A){
int n;
if(A.getdim()>dim)
n=A.getdim();
else
n=dim;
Cvector temp(n);
for(int i=0;i<n;i++)
temp.setC(i,getC(i)+A.getC(i));
return temp;
}
When I run the following code, everything works fine:
Cvector X(2);
Cvector Y(3);
defines the objects of dimension 2 and 3
X.setC(0,1);
X.setC(1,4);
Y.setC(0,0);
Y.setC(1,6);
Y.setC(2,9);
adds the corresponding values to each dimension (2 for X and 3 for Y)
X.desplegar();
Y.desplegar();
Cvector T=Y+X;
T.desplegar();
Everything is displayed correctly up til here, T displays the sum of vector Y and vector X, which is what I want. But when I run
X.desplegar();
it only displays unrelated data from memory, it seems that object X is modified when it is passed as an argument to operator +, why is this so? If I instead use pointers to the objects this does not happen, but it does not seem intuitive for this to happen.
can anyone comment?
When you overload the operator + with argument pass-by-value, the copy constructor is invoked to instantiate a temporary object. By default, the copy constructor is a bitwise copy of the original object. And just before the method returns, the destructor, which is user-defined, is invoked on the temp object, where the underlying storage is deallocated.
To correct the code, please define the copy constructor yourself or pass the argument by reference.
Please always remember the rule-of-three, that is when you've defined any of destructor, copy constructor, and assignment operator, please consider also define the others among these three.
The problem is in your operator+.
Cvector Cvector::operator + (Cvector A)
Here, you are passing the second operand (which, in your case is X) by making a copy of it. This copy (A) will have it's C pointer pointing to the same memory as your X vector:
Cvector T=Y+X;
In the end of the operator+, the copy will get destroyed, the destructor will be called, and the memory will be freed. Since this memory is shared by the copy of X, and X itself, you will have garbage. Change your operator+ so it takes a reference and everything will work fine:
Cvector Cvector::operator + ( const Cvector & A )
Note that it is also a good idea to implement a copy constructor.
You copy vectors incorrectly. temp has its destructor automatically invoked at the end of operator+, causing T to have a dangling pointer. You might be doing something similar to X, it's hard to tell without looking at the complete program.
Cvector doesn't have a copy constructor, so the default one will be generated:
Cvector::Cvector(Cvector const & original)
: dim(original.dim), C(original.C)
{}
this does a shallow copy, that is, you now have two objects with the same C pointer.
So, when you copy X as the argument to any function, this happens:
Cvector x;
// populate X
// now call this:
void foo(Cvector y) { // y is created as a copy of x
} // y is destroyed
when the copied argument is destroyed, it deletes C, which is shared with the original.
These changes should be made:
write proper a copy constructor and assignment operator, that perform a deep copy (this will stop copies from breaking the original object when destroyed)
pass arguments by const reference when you're not changing them
I have a class A which dynamically allocates memory for an integer(pointed by a class memeber say _pPtrMem) in its constructor and deallocates the same in destructor. To avoid Shallow copy, I have overloaded assignment operator and copy constructor. The widely used way in which assignment operator is overloaded is as following:
A& operator = (const A & iToAssign)
{
if (this == & iToAssign) // Check for self assignment
return *this;
int * pTemp = new int(*(iToAssign._pPtrMem)); // Allocate new memory with same value
if (pTemp)
{
delete _pPtrMem; // Delete the old memory
_pPtrMem = pTemp; // Assign the newly allocated memory
}
return *this; // Return the reference to object for chaining(a = b = c)
}
Another way for implementing the same could be
A& operator = (const A & iToAssign)
{
*_pPtrMem= *(iToAssign._pPtrMem); // Just copy the values
return *this;
}
Since the second version is comparatively much simpler and faster(no deallocation, allocation of memory) why is it not used widely? Any problems that I am not able to make out?
Also we return an object of the same type from the assignment operator for chaining(a = b = c)... so instead of returning *this is it fine to return the iToAssign object as both objects are supposedly now equal?
Usually, the best way to implement a copy assignment operator is to provide a swap() function for your class (or use the standard one if it does what you want) and then implement the copy assignment operator via the copy constructor:
A& A::operator= (A iToAssign) // note pass by value here - will invoke copy constructor
{
iToAssign.swap(*this);
return *this;
}
// void swap(A& other) throws() // C++03
void A::swap(A& other) noexcept
{
std::swap(_pPtrMem, other._pPtrMem);
}
This makes sure that your copy assignment operator and copy constructor never diverge (that is, it cannot happen that you change one and forget to change the other).
No, there is no problem with your implementation. But having one integer dynamic allocated is at least very special.
This implementation is not widely used, because no one allocates a single integer on the free store. You usually use dynamic allocated memory for arrays with a variable length unknown at compile time. And in this case it's most of the time a good idea to just use std::vector.
No it's not fine, to return an different object. Identity is not the same as equality:
T a, b, d;
T& c = a = b;
c = d; // should change a, not b
Would you expect that the third line changes b?
Or a event better Example:
T a;
T& b = a = T();
This would result in a dangling reference, referencing an temporary and destructed object.
The first version is used in case _pPtrMem is a pointer to some basic type for instance a dynamically allocated array. In case the pointer is pointing to a single object with correctly implemented assignment operator the second version will do just as good. But in that case I don't think you will need to use a pointer at all.
In the second case, if _pPtrMem was initially unassigned, the line
*_pPtrMem= *(iToAssign._pPtrMem); // Just copy the values
is causing an assignment to an invalid memory location (possibly a segmentation fault). This can only work if _pPtrMem has been allocated memory prior to this call.
In this case, the second implementation is by far the better.
But the usual reason for using dynamic in an object is because
the size may vary. (Another reason is because you want the
reference semantics of shallow copy.) In such cases, the
simplest solution is to use your first assignment (without the
test for self-assignment). Depending on the object, one might
consider reusing the memory already present if the new value
will fit; it adds to the complexity somewhat (since you have to
test whether it will fit, and still do the
allocation/copy/delete if it doesn't), but it can improve
performance in certain cases.
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.
During deep copy we are writing overloaded copy constructor and assignment operator.
May i know why we have to write the overloaded assignment operator because we doing the same in overloaded copy constructor(except some check and return this).
Who is calling assignment operator
Follow the Rule of Three:
If you need to write an copy constructor for your class, You also should write the Copy assignment operator and Destructor.
Copy Assignment operator and Copy Constructor both are called Copying functions. They basically help in getting a new copy of an object from an existing object. They both are separate entities invoked in different scenarios. So, just as in case of Copy constructor you ensure that you make deep copies of all pointer members and not just shallow copies, same would applies for copy assignment operator.
An Code Example:
class MyClass obj1, obj2;
class MyClass obj3(obj1); //Calls Copy Constructor
obj1 = obj2; //Calls Copy Assignment Operator
The assignment operator is used if you do this:
MyType my1, my2;
my1 = my2; // same as: my1.operator=(my2);
The copy constructor and the assignment operator usually have very similar code, but if done properly (initializer lists) should be coded differently, used differently, and perform differently.
The copy constructor should use initializer lists. This is used for creating a new vector object that is the same as one already existing.
vector::vector(const vector& b)
:size(b.size),
capacity(b.capacity),
data(new TYPE[size])
{
//there should be minimal code here
//I'm skipping copying the data, because doing it right
//is hard and beside the point
}
vector seven;
seven.push_back(7);
vector seven_copy(seven); //make a new one, same as old
The assignment operator is probably exactly what you have. This is used to reassign an already existing vector object to be the same as one already existing
vector& vector::operator=(const vector& b)
{
//carefully written so self assignment doesn't crash.
TYPE* temp = new TYPE[b.size];
//I'm skipping copying the data, because doing it right
//is hard and beside the point
delete [] data;
//all exceptions that can be thrown, have, so it's safe to modify members now
data = temp;
size = b.size;
capacity = b.capacity;
return *this;
}
vector nine;
nine.push_back(9);
nine = seven; //make an old one the same as another old
It should be noted that the move constructor and move assignment may look vaguely similar, but should probably be different as well.
vector::vector(vector&& b)
:size(b.size)
capacity(b.capacity)
data(b.data) //different!
{
b.data = nullptr;
}
vector& operator=(vector&& b)
{
//since b.data is tied to b.size and b.capacity, it's safest to just swap
//so if someone calls b.push_back() after, it's all still safe.
std::swap(size, b.size);
std::swap(capacity, b.capacity);
std::data(data, b.data);
return *this;
}