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?
AFAIK this will construct/destruct
E
objects redundantly
It would appear so. The new
ed array already applies the default constructor and the delete[]
would call destructor as well for all the elements. In effect, the Add()
and Remove()
methods add little other than maintain the size
counter.
When using placement new, would
new char[sizeof(E)*100]
be the correct way for allocating the buffer?
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 a std::array
would be far better options for managing the elements in the container.