I'm a noob in c++. I have a problem that I cannot solve anyway. I wrote a code to understand better classes and overload operator:
#include <iostream>
#include <stdlib.h>
#include <stdarg.h>
using namespace std;
class vectmy {
public:
int size;
int *a;
vectmy(int n,int val);
~vectmy (){delete[] a; //IF I DELETE THIS PROGRAM WORKS
}
vectmy & operator = (const vectmy &);
};
vectmy::vectmy(int n,int val){
size=n;
a = new int[ n+1 ];
for (int i=0;i<n;++i){
*(a+i)=val;
}
}
vectmy& vectmy::operator= (const vectmy& param)
{
for (int i=0;i<3;++i) a[i]=param.a[i];
return *this;
}
vectmy operator+( vectmy left, vectmy right)
{
vectmy result = left;
for (int i=0;i<3;++i) result.a[i]=result.a[i]+right.a[i];
return result;
}
int main() {
int b1[3]={1,2,4};
vectmy d(3,2),b(3,4),c(3,0);
c=(b+d);
for (int j=0; j<3; ++j)cout<<c.a[j]<<' '<<endl;
return 0;
}
When I run it crashes. If I remove the destructor it works. Why it happens?
When I run it crashes. If I remove the destructor it works. Why it happens?
Your operator + creates a copy of left here:
vectmy result = left;
Since you haven't defined a copy constructor explicitly, the compiler will generate one implicitly that performs member-wise copying.
A dull copy of the a data member means that the a pointer will eventually point to the same location for two different instances of vectmy (result and left), both of which will delete[] it upon destruction.
Such double deletion gives your program undefined behavior, which in your case manifests itself as a crash.
This is the point of the Rule of Three: every time you have a user-defined copy-constructor, assignment operator, or destructor, you should probably define all of them.
The reason is that you normally define one of those functions because you are managing some resource (memory, in your case), and you usually want to perform proper actions when copying, destructing, or assigning objects that manage a resource.
In this particular case, a proper copy constructor is missing. This is how you could define it:
vectmy::vectmy(vectmy const& v)
{
size=v.size;
a = new int[size];
*this = v;
}
Also, I would suggest you to avoid manual memory management through raw pointers, new, and delete (or their array counterparts) whenever you can, and consider using std::vector instead.
UPDATE:
Also notice, that your operator + is accepting its parameters by value, which means that each argument will be copied (i.e., the copy constructor will be invoked).
Since a copy is not really necessary here, you may want to take your parameters by reference (to const):
vectmy operator + ( vectmy const& left, vectmy const& right)
// ^^^^^^ ^^^^^^
In your operator+ you do
vectmy result = left;
This will call the default constructor and copy constructor, of which you have none. So the compilers variants will be used, which doesn't allocate memory for the a member. For the automatically generated copy constructor the pointer will simply be copied, making two object use the same pointer. When one deletes it, the other pointer becomes invalid.
You should read about the rule of three.
Related
EDIT: I had to use unique_ptr or follow the rule-of-five I'm still learning about it so I used unique_ptr and it worked. But I have a question, the destructor now is being called twice and I think that is no problem as long as the block of memory that the pointer is pointing to is not being freed twice, Right??
I made a simple "String" class in c++ (Know it from The Cherno). So I made it and it seems to work well until I decided to add an empty constructor to be able to initialize it with no parameter but when I did that the destructor is being called twice.
// here is the header file
#pragma once
#include <iostream>
using namespace std;
class String
{
private:
//Hold the raw of chars in the heap memory
char* m_Buffer;
//The size of the buffer in heap
unsigned int m_Size;
public:
//An empty Constructor
String()
: m_Buffer(nullptr), m_Size(0)
{
cout << "created Empty." << endl;
}
// A Constructor
String(const char* string)
{
m_Size = strlen(string);
m_Buffer = new char[m_Size + 1];
memcpy(m_Buffer, string, m_Size + 1);
m_Buffer[m_Size] = 0;
}
// A destructor
~String()
{
cout << "Destroy!!" << endl;
delete[] m_Buffer;
}
// Function resposable for coping
String(const String& other)
: m_Size(other.m_Size)
{
m_Buffer = new char[m_Size + 1];
memcpy(m_Buffer, other.m_Buffer, m_Size + 1);
}
char& operator[](unsigned int& index)
{
return m_Buffer[index];
}
friend std::ostream& operator<<(std::ostream& stream, const String& other);
};
std::ostream& operator<<(std::ostream& stream, const String& other)
{
stream << other.m_Buffer << endl;
return stream;
}
//here is the main file
#include "LclString.h"
int main()
{
String a = "asdc";
a = "ads"; // The Destructor is being called here the first time
cin.get();
} // and here is the second time
A piece of advice will be appreciated
......................................
Your destructor calls delete[] m_Buffer. A pointer may never be deleted twice. If you do delete a pointer twice, then the behaviour of the program will be undefined. You must avoid ever doing that. To achieve avoiding that, you must make sure that no two instances of the class have the same pointer value in the member.
Consider what the implicitly generated assignment operator of your class does. It copies all members from the right hand operand to the left hand operand. Can you see why that is a problem? All members include the m_Buffer pointer. The assignment operator will cause two instances of the class to have the same pointer. And when the second instance is destroyed, it deletes that same pointer again. And the behaviour of the program is undefined.
There is another related problem, the implicit assignment operator overwrites the old m_Buffer. Who's going to delete the pointer that was overwritten? No-one is going to delete it because the value was lost by the assignment. That's a memory leak.
Conclusion:
Avoid using owning bare pointers.
Avoid using new and delete directly.
If you have a user defined destructor, then you probalby also need user defined copy/move constructor and assignment operator. This is known as rule of 5 (previously rule of 3). If you use smart pointers instead of owning bare pointers, then you usually don't need a user defined destructor.
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.
So my problem is this...when I am trying to allocate memory to a pointer, it fails.
This is my MatrixClass definition..
class MatrixClass
{
public:
MatrixClass(int m, int n);
MatrixClass(void);
virtual ~MatrixClass(void);
double getRead(int num1, int num2) const;
double& getReadWrite(int num3, int num4);
void set(int i,int j,double value);//set value at i,j to value
MatrixClass(const MatrixClass &rhs);
void assign(int M,int N);
MatrixClass sum1(const MatrixClass& rhs) const;
MatrixClass operator+(const MatrixClass& rhs);//overloading the + operator
MatrixClass operator-();
private:
double* dataptr;
int M;
int N;
};
I am trying to do this..
MatrixClass BB;
BB = A + B;
So here is my overloaded + function..
MatrixClass MatrixClass::operator +(const MatrixClass &rhs)
{
MatrixClass temp;
//temp.M = this->M + rhs.M;
//temp.N = this->N + rhs.N;
for(int i = 0;i < M;i++)
{
for(int j = 0; j<N;j++)
{
temp.dataptr[i * N + j] = this->getReadWrite(i,j) + rhs.dataptr[i*N+j];
}
}
return temp;
}//end operator +
Once temp returns...it calls the copy constructor...passing temp as 'rhs' and 'this' would refer to 'BB'? (Am I right in thinking this?)
MatrixClass::MatrixClass(const MatrixClass &rhs)//copy constructor
{
this->M = rhs.M;
this->N = rhs.N;
dataptr = 0;
if(rhs.dataptr != 0)
{
dataptr = new double[M * N];//allocate memory for the new object being assigned to...
// the line here where I try to allocate memory gives me an error.....Am I right in
//thinking that this would be assigning memory to dataptr of 'BB'?? Values are assigned to //'M' and 'N' fine....
int num = sizeof(double);
memcpy(this->dataptr,rhs.dataptr,M*N*sizeof(double));
}
else
{
this->dataptr = 0;
}
}//end copy constructor
Also the error that i get is this... 'Unhandled exception at 0x75a0b727 in assignment.exe: Microsoft C++ exception: std::bad_alloc at memory location 0x002af924..'
So basically the qestion I am asking is..why the hell is is the line where I am trying to allocate memory to 'dataptr' in the copy constructor giving me problems..it only does this when calling the copy constructor from the return value 'temp'..
Thanks!
Short answer: you have not implemented Rule of Three properly. In C++11, Rule of Five.
Long answer: you have not implemented operator=. The compiler generated one is not enough for your case.
Apart from that my guess is that your default constructor doesn't allocate memory for dataptr. If so, then you're using dataptr in operator+ without even allocating memory for it. That is the reason why your program crashes. Even if the default constructor allocates memory, the problem is still there as the value of rhs.M and rhs.N may be different from what you assume in the default constructor (which is, as you said, 4 and 5 respectively).
So allocate memory for dataptr in operator+. Also, before allocation, you've to deallocate the memory which it may point to, and you also need to set M and N to the values of rhs.M and rhs.N respectively.
No, James, you're wrong, when operator+ returns the copy constructor will be called to covert local variable temp into a temporary anonymous object in the scope of the assignment operator. In the copy constructor, this will refer to this temporary variable, not BB.
Because the LHS already exists, it will not be "constructed" again when operator+ returns, it will be "assigned", so you need to overload operator=. (See here for much more detail.) The default operator= just makes a bitwise copy, so if you didn't overload operator=, the dataptr would be freed (we hope) in the destructor of the anonymous temporary object when it is destroyed as it goes out of scope (which is immediately after it is copied) and BB would be pointing to freed memory. You would also leak any memory already allocated in BB as BB would not be destroyed before being assigned. BB's dataptr would leak while the temporary object's dataptr would be freed twice.
So, although it kind of sucks that you end up allocating and copying memory three times, in order to make + and = work in all situations, you need to do the following:
In operator+ change MatrixClass temp; to MatrixClass temp(rhs.M, rhs.N); so that temp.dataptr is properly allocated and deallocated.
As you are doing, in the copy constructor allocate new memory for dataptr and copy it over.
Overload operator= so that it first checks for self-assignment (this == &rhs) and if it is not self-assigning, frees the existing dataptr and then allocates a new one and copies the rhs.
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).
I've been exploring the possibilities of Move Constructors in C++, and I was wondering what are some ways of taking advantage of this feature in an example such as below. Consider this code:
template<unsigned int N>
class Foo {
public:
Foo() {
for (int i = 0; i < N; ++i) _nums[i] = 0;
}
Foo(const Foo<N>& other) {
for (int i = 0; i < N; ++i) _nums[i] = other._nums[i];
}
Foo(Foo<N>&& other) {
// ??? How can we take advantage of move constructors here?
}
// ... other methods and members
virtual ~Foo() { /* no action required */ }
private:
int _nums[N];
};
Foo<5> bar() {
Foo<5> result;
// Do stuff with 'result'
return result;
}
int main() {
Foo<5> foo(bar());
// ...
return 0;
}
In this above example, if we trace the program (with MSVC++ 2011), we see that Foo<N>::Foo(Foo<N>&&) is called when constructing foo, which is the desired behaviour. However, if we didn't have Foo<N>::Foo(Foo<N>&&), Foo<N>::Foo(const Foo<N>&) would be called instead, which would do a redundant copy operation.
My question is, as noted in the code, with this specific example which is using a statically-allocated simple array, is there any way to utilize the move constructor to avoid this redundant copy?
First off, there's a general sort of advice that says you shouldn't write any copy/move constructor, assignment operator or destructor at all if you can help it, and rather compose your class of high-quality components which in turn provide these, allowing the default-generated functions to Do The Right Thing. (The reverse implication is that if you do have to write any one of those, you probably have to write all of them.)
So the question boils down to "which single-responsibility component class can take advantage of move semantics?" The general answer is: Anything that manages a resource. The point is that the move constructor/assigner will just reseat the resource to the new object and invalidate the old one, thus avoiding the (presumed expensive or impossible) new allocation and deep copying of the resource.
The prime example is anything that manages dynamic memory, where the move operation simply copies the pointer and sets the old object's pointer to zero (so the old object's destructor does nothing). Here's a naive example:
class MySpace
{
void * addr;
std::size_t len;
public:
explicit MySpace(std::size_t n) : addr(::operator new(n)), len(n) { }
~MySpace() { ::operator delete(addr); }
MySpace(const MySpace & rhs) : addr(::operator new(rhs.len)), len(rhs.len)
{ /* copy memory */ }
MySpace(MySpace && rhs) : addr(rhs.addr), len(rhs.len)
{ rhs.len = 0; rhs.addr = 0; }
// ditto for assignment
};
The key is that any copy/move constructor will do a full copying of the member variables; it is only when those variables are themselves handles or pointers to resources that you can avoid copying the resource, because of the agreement that a moved object is no longer considered valid and that you're free to steal from it. If there's nothing to steal, then there's no benefit in moving.
In this case it's not useful because int has no move-constructors.
However, it could be useful if those were strings instead, for example:
template<unsigned int N>
class Foo {
public:
// [snip]
Foo(Foo<N>&& other) {
// move each element from other._nums to _nums
std::move(std::begin(other._nums), std::end(other._nums), &_nums[0]);
}
// [snip]
private:
std::string _nums[N];
};
Now you avoid copying strings where a move will do. I'm not sure if a conforming C++11 compiler will generate equivalent code if you omit all the copy-/move-constructors completely, sorry.
(In other words, I'm not sure if std::move is specially defined to do an element-wise move for arrays.)
For the class template you wrote, there's no advantage to take in a move constructor.
There would be an advantage if the member array was allocated dynamically. But with a plain array as a member, there's nothing to optimize, you can only copy the values. There's no way to move them.
Usually, move-semantic is implemented when your class manages resource. Since in your case, the class doesn't manages resource, the move-semantic would be more like copy-semantic, as there is nothing to be moved.
To better understand when move-semantic becomes necessary, consider making _nums a pointer, instead of an array:
template<unsigned int N>
class Foo {
public:
Foo()
{
_nums = new int[N](); //allocate and zeo-initialized
}
Foo(const Foo<N>& other)
{
_nums = new int[N];
for (int i = 0; i < N; ++i) _nums[i] = other._nums[i];
}
Foo(Foo<N>&& other)
{
_nums = other._nums; //move the resource
other._nums=0; //make it null
}
Foo<N> operator=(const Foo<N> & other); //implement it!
virtual ~Foo() { delete [] _nums; }
private:
int *_nums;
};