Recently I got a task to do in C++, implement a Set class with union, intersection etc. as overloaded operators. I've got a problem with overloading an operator+(). I decide to use vectors and get the advantage of some algorithm's library functions. The problem is I HAD TO pass to constructor an array pointer and array size. This complicated this task a bit... I can compile it but during the "z=a+b" operation I encounter somekind of memory leak. Can anyone explain me what am I doing wrong?
class Set {
int number; // array size (can't be changed)
int *elems; // array pointer (same)
public:
Set();
Set(int, int*); // (can't be changed)
~Set();
friend Set operator+(const Set& X,const Set& Y){
std::vector<int> v(X.number+Y.number);
std::vector<int>::iterator it;
it=std::set_union (X.elems, X.elems+X.number, Y.elems, Y.elems+Y.number, v.begin());
v.resize(it-v.begin());
Set Z;
Z.number=v.size();
Z.elems=&v[0];
return Z;
}
};
Set::Set(){};
Set::Set(int n, int* array){
number=n;
elems = array = new int[number];
for(int i=0; i<number; i++) // creating Set
std::cin >> elems[i];
std::sort(elems, elems + number);
}
Set::~Set(){
delete[] elems;
}
int main(){
int* pointer;
Set z;
Set a = Set(5, pointer);
Set b = Set(2, pointer);
z=a+b;
}
I added copy constructor and copy assingment, changed the operator+() as NathanOliver advised and now I am passing to constructor static array. Still have memory leak and strange thing is that I got this memory leak even when in main there is only class variable initialization, doesn't matter if with parameters or not... Any suggestions? I think cunstructor is valid.
Set::Set(int n, int* array){
number = n;
elems = array;
std::sort(elems, elems + number);
}
Set::Set(const Set& s){
number=s.number;
elems=s.elems;
}
Set& operator=(const Set& X){
if(this==&X)
return *this;
delete [] elems;
elems=X.elems;
number=X.number;
return *this;
I use gcc (tdm64-2) 4.8.1 compiler.
When you have
z=a+b
, the assignment operator for theSet
class is used. You didn't define a custom version of this operator, so the default compiler-generated one is used. This compiler-generated assignmentoperator=()
simply does a member-wise copy.Since you have raw owning pointers in your
Set
class, this doesn't work correctly: the default compiler-generatedoperator=()
shallow-copies pointers, instead you should deep-copy the data.An option to fix this is to define your own version of
operator=()
, paying attention to do proper deep-copy of source data.Note that in this case you also should define a copy constructor.
But a better option would be to get rid of the owning raw pointer data members, and instead use a RAII building block class, like
std::vector
.So, for example, instead of these data members:
you could just have a single:
If you do that, the default compiler-generated
operator=()
will work just fine, since it will copy thestd::vector
data member (not the raw owning pointers), andstd::vector
knows how to properly copy its content without leaking resources.In
You create a vector, modify it and then set the
elems
to point to what the vector contains. The issue with that is that when the vector is destroyed at the end of the function the memory that the vector held is released. So you now have a pointer pointing to memory you no longer own. Trying to do anything with it is undefined behavior. What you could do is create a new array, copy the elements of thevector
into the array and then assign the new array to `elemsSecondly you need to define a copy constructor and assignment operator for you class. To do that reference: What is The Rule of Three?
The best solution (but I can't tell if you're allowed to do this specifically) is to use
vector
internally in yourSet
and assign it from the passed in pointer and length using the two-iterator constructor.Now if that's not possible you need to properly manage the memory of your class:
operator+
you can't create a local vector and then take the address of its memory, that memory will disappear as soon as the operator returns.