Debug_VLD in VS2010 reveals some memory leaks that come from class member creation / initialization / deletion.
my_member
is a data member with type double*. In constructor, I have
my_member = NULL ;
Then in some method, i need to allocate memory for my_member
. I cannot do so in constructor,
since i dont know size of array yet, and/or size may different for different calls of the method. What i do in this method is checking if member is NULL. if so, i allocate space for it, if not, i can operate on array (changing value for its element with accesor []). It looks like
void MyClass::my_method()
{
if( my_member == NULL )
my_member = new double[n_dim] ;
for(int k = 0 ; k < n_dim ; k++ )
my_member[k] = k ;
}
and memory leak occurs at line my_member = new double[n_dim] ;
.
In destructor, i have
delete[] my_member ;
what is wrong? how to do allocation properly ?
thanks!
Using std::vector<double>
is the preferred way, but if you want to have raw double*
and write copy constructor, move constructor and operator=
"by hand", you should do something like this:
#include <assert.h> // for assert
#include <algorithm> // for std::swap
class MyClass
{
//
// Raw array
//
double * m_ptr; // raw pointer
size_t m_dim; // number of items in the array
public:
// Default constructor - creates empty vector
MyClass()
: m_ptr(nullptr)
, m_dim(0)
{
}
// Copy constructor
MyClass(const MyClass& src)
: m_ptr(nullptr)
, m_dim(0)
{
// Special case of empty source
if (src.m_dim == 0)
{
assert(src.m_ptr == nullptr);
return;
}
// Allocate and deep-copy from source
m_ptr = new double[src.m_dim];
m_dim = src.m_dim;
for (size_t i = 0; i < m_dim; i++)
m_ptr[i] = src.m_ptr[i];
}
// Move constructor: steal the "guts" from src
MyClass(MyClass&& src)
{
m_ptr = src.m_ptr;
src.m_ptr = nullptr;
m_dim = src.m_dim;
src.m_dim = 0;
}
// Destructor
~MyClass()
{
delete [] m_ptr;
}
// Unified operator=
MyClass& operator=(MyClass src)
{
std::swap(m_ptr, src.m_ptr);
std::swap(m_dim, src.m_dim);
return *this;
}
};
If there's any other place in the code where you set my_member
to NULL
without calling delete[]
, then yes. If you don't obey the rule of three (properly implemented copy constructor and assignment operator), you'll run into all sorts of trouble.
To prevent this, use a std::vector<double>
instead, where you can do:
void MyClass::my_method()
{
my_member.resize(n_dim); // yay, learned something new here
for(int k = 0 ; k < n_dim ; k++ )
my_member[k] = k ;
}
That way, you're not managing memory, so there's no need for a destructor (unless it's virtual
, in which case it can be empty).