I maintain a old C++ application which has a lot of classes like below:
class ClassWithALotOfVectors
{
std::vector<int> _vector1;
std::vector<int> _vector2;
// a lot of other vector datamembers go here
std::vector<double> _vectorN;
};
that is - a data type where members a vectors of double or int. The thing is - these vectors are never populated at the same time - and therefore when we create 100000 instances of ClassWithALotOfVectors - memory usage adds up to impressive number even though only 10% of these vector are in use.
So I decided to write a small "allocate on demand" vector class.
It is a wrapper around std::vector - where internal vector only create when accessed for the first time (using two getters - ref() & const_ref() methods)
When I replaced std::vector in a ClassWithALotOfVectors class with a compact_vector as below:
class ClassWithALotOfVectors2
{
compact_vector<int> _vector1;
compact_vector<int> _vector2;
compact_vector<double> _vectorN;
};
did a few tests and the results were promising - memory usage went down dramatically, but suddenly found that application does not release memory at the end - the memory consumptions grows in much slower rate than it is used to be - but application does not seem to be deallocating the memory at the end.
Can you look at my implementation of the compact_vector and see if you can spot something wrong with a memory management.
template <class T> class compact_vector
{
public:
compact_vector<T>()
:_data(NULL)
{
}
~compact_vector<T>()
{
clear();
}
compact_vector<T>(const compact_vector<T> & rhs)
:_data(NULL)
{
if (NULL != rhs._data)
{
_data = new std::vector<T>(*(rhs._data));
}
else
{
clear();
}
}
// assignment
//
compact_vector<T> & operator=(const compact_vector<T> & rhs)
{
if (this != &rhs)
{
clear();
if (NULL != rhs._data)
{
_data = new std::vector<T>(*rhs._data);
}
}
return *this;
}
compact_vector<T> & operator=(const std::vector<T> & rhs)
{
clear();
if (!rhs.empty())
{
_data = new std::vector<T>(rhs);
}
return *this;
}
const std::vector<T> & const_ref()
{
createInternal();
return *_data;
}
std::vector<T> & ref()
{
createInternal();
return *_data;
}
void clear()
{
if (NULL != _data)
{
_data->clear();
delete _data;
_data = NULL;
}
}
private:
void createInternal()
{
if (NULL == _data)
{
_data = new std::vector<T>();
}
}
private:
compact_vector<T>(const std::vector<T> & rhs)
{
}
compact_vector<T>(std::vector<T> & rhs)
{
}
compact_vector<T>(std::vector<T> rhs)
{
}
std::vector<T> * _data;
};