This is placement new.
Though you don;t usually use it with integer types.
It is usually used to build a buffer where you then build other types into.
// Allocate a buffer with enough room for two T objects.
char* buffer = new char[sizeof(T) * 2];
// Allocate a T in slot zero
T* t1 = new (buffer + 0 * sizeof(T)) T("Zero");
// Allocate a T in slot one
T* t2 = new (buffer + 1 * sizeof(T)) T("One");
Thats the basics.
But remember that the objects allocated with placement new can not be deleted with the delete
statement. This is because delete
tries to reclaim memory allocated by new
(as well as call the destructor). So to use these objects correctly you must manually call there destructor.
t1->~T();
t2->~T();
Don't forget to delete the original buffer.
delete [] buffer;
A few other caveats:
People often see that buffer could be implemented on the stack and thus be automatically freed
char buffer[sizeof(T) * 2];
Unfortunately this may be technically OK (It compiles). But it is not guaranteed to work as the memory of buffer may not be aligned correctly for a T to be placed inside. So you must allocate the buffer dynamically (by using new it gurantees that the memory is aligned correctly for any object of the size allocated (thus by extension it is also aligned for any size smaller then the size allocated). The easy way to get around this problem is to use a std::vector
std::vector<char> buffer(sizeof(T) * 2);
T* t1 = new (&buffer[0] + 0 * sizeof(T)) T("Zero");
T* t2 = new (&buffer[0] + 1 * sizeof(T)) T("One");
Another use of placement new is to reset an object.
I have seen this done but I prefer to use the more standard assignment operator:
T obj1("Plop");
obj1 = T("Another Plop");
// Can be done like this:
T obj1("Plop");
obj1.~T();
new (&obj1) T("Another Plop"); // Seems excessive to me. But can be us-full
// in some extreme situations.
Remember if you use the reset method you must destroy the old object first (or the object may not behave correctly).