I've seen many posts about memory allocation in C++, questions about "new operator" vs "operator new", questions about new int(100) vs new int[100], questions about memory initialization... I think there should be an answer that summarizes everything clearly once and for all, and I'm choosing this question to write this summary. It is about dynamic memory allocation, ie allocations on the heap at runtime. I also provide a summary implementation (public domain).
C vs C++
Main functions for dynamic memory allocations:
- In C (header <cstdlib>), we have mainlymallocandcallocandfree. I won't talk aboutrealloc.
- in C++ (header <new>), we have:
- Template single-object allocation with initialization arguments:
- new T( args )
- new (std::nothrow) T( args )
- delete ( T* )
 
- Template multiple-objects allocation with default initialization:
- new T[ size_t ]
- new (std::nothrow) T[ size_t ]
- delete[] ( T* )
 
- Template memory initialization without allocation for single or multiple objects:
- new (void*) T( args )
- new (void*) T[ size_t ]
 
- Internal new-expressions for:
- Raw memory allocation ::operator new( size_t );
- Raw memory allocation without exception ::operator new( size_t, std::nothrow );
- Raw memory initialization without allocation ::operator new( size_t, ptr ).
 
 
Please look at this post for a concise comparison.
Legacy C dynamic allocations
Main points: complete type-erasure (void* pointers), and therefore no construction/destruction, size specified in bytes (typically using sizeof).
malloc( size_t ) does not initialize memory at all (raw memory contains garbage, always initialize manually before use). calloc( size_t, size_t ) initializes all bits to 0 (slight overhead, but useful for POD numeric types). Any allocated memory should be released using free ONLY. 
Construction/destruction of class instances should be done manually before use / before memory release.
C++ dynamic allocations
Main points: confusing because of similar syntaxes doing different things, all delete-statements call the destructor, all delete-statements take fully typed pointers, some new-statements return fully-typed pointers, some new-statements call some constructor.
Warning: as you will see below, new can either be a keyword OR function. It is best not to talk about "new operator" and/or "operator new" in order to avoid confusions. I call "new-statements" any valid statements that contain new either as a function or keyword. People also talk about "new-expressions", where new is the keyword and not the function.
Raw memory allocation (no initialization)
Do not use this yourself. This is used internally by new-expressions (see below).
These allocations do not initialize memory, and in particular, they do not call the default-constructor on the allocated objects. Therefore you MUST initialize ALL the elements manually before you release the allocation using either delete or delete[].
Note: I couldn't stress enough that you should NOT use this yourself. If you should use it, however, make sure you pass a pointer to void instead of a typed pointer when calling either delete or delete[] on such allocations (always after initializing manually). I have personally experienced runtime errors with non-POD types with some compilers (maybe my mistake).
Raw memory initialization (no allocation)
Do not use this yourself. This is used internally by new-expressions (see below).
In the following, I assume void *ptr = ::operator new( n*sizeof(T) ) for some type T and size n.
Then ::operator new( n*sizeof(T), (T*) ptr ) initializes n elements of type T starting from ptr using the default constructor T::T(). There is no allocation here, only initialization using the default-constructor.
Single-object allocation & initialization
- new T( args )allocates and initializes memory for a single object of type- Tusing the constructor- T::T( args ). The default constructor will not be called unless arguments are omitted (ie- new T()or even- new T). Throws an exception- std::bad_allocon failure.
- Same for new (std::nothrow) T( args )except that it returnsNULLin case of failure.
- Use deleteto call the destructorT::~T()and release the corresponding memory.
Multiple-objects allocation & initialization
- new T[n]allocates and initializes memory for a- nobjects of type- Tusing the default constructor. Throws an exception- std::bad_allocon failure.
- Idem for new (std::nothrow) T[n]except that it returnsNULLin case of failure.
- Use delete[]to call the destructorT::~T()for each element and release the corresponding memory.
Memory initialization (aka "placement new")
No allocation here. Regardless of how the allocation was made: 
- new (ptr) T(args)calls the constructor- T::T(args)on the memory stored at- ptr. The default constructor is not called unless arguments are omitted.
- new (ptr) T[n]calls the default constructor- T::T()on- nobjects of type- Tstored from- ptrto- ptr+n(ie,- n*sizeof(T)bytes).
Related posts