I just came across some container implementation in C++. That class uses an internal buffer to manage its objects. This is a simplified version without safety checks:
template <typename E> class Container
{
public:
Container() : buffer(new E[100]), size(0) {}
~Container() { delete [] buffer; }
void Add() { buffer[size] = E(); size++; }
void Remove() { size--; buffer[size].~E(); }
private:
E* buffer;
int size;
};
AFAIK this will construct/destruct E
objects redundantly in Container()
and ~Container()
if new
/delete
are not customized. This seems dangerous.
Is using placement new
in Add()
the best way to prevent dangerous redundant constructor / destructor calls (apart from binding the class to a fully featured pool)?
When using placement new
, would new char[sizeof(E)*100]
be the correct way for allocating the buffer?
It would appear so. The
new
ed array already applies the default constructor and thedelete[]
would call destructor as well for all the elements. In effect, theAdd()
andRemove()
methods add little other than maintain thesize
counter.The best would be to opt for the
std::allocator
that handles all of the memory issues for you already.Using a placement
new
and managing the memory yourself requires you to be aware of a number of issues (including);None of these are impossible to surmount, it has just already been done in the standard library. If you are interested in pursuing a custom allocator, the global allocation functions (
void* operator new (std::size_t count);
) would be the appropriate starting point for the memory allocations.Without further explanation on the original purpose of the code - a
std::vector
or astd::array
would be far better options for managing the elements in the container.