I'm learning about Dynamic Memory Allocation in C++ and the keywords new
and new[]
are mentioned.
It is said to enable users to specify the size of the memory allocation at runtime, unlike simply declaring a variable or array with a fixed size in the source code.
I don't understand this concept. How does it work? I just need a clarification on the idea and an example would be helpful!
So, if you want an array of 10 integers, you'd be writing:
But what if you wanted to do something like this;
Well, the C++ language doesn't allow that. Instead, you have to do:
to create your array. And later on you MUST[1] use:
to free the memory.
So, how does this work? When you call new, the C++ runtime library [the code that you didn't have to write that makes up the fundamentals of C++] will figure out how much space
num
integers take up, and find some space in memory for that. I'm not going into details of "how you find some memory". For now, just trust me, there is some memory available somewhere that can be used to store some integers in.When you later call
delete
, that same memory is given back to the "pool" or "heap" of memory that it came from.Of course, if you have a machine with, say, 256 MB of memory, and you try to ask for space to store 250 million integers, bearing in mind that an integer takes up more than one byte, it's not going to work out - there is no "magic" here - the memory is still limited to how much is available in the machine.... You just have the right to determine in the program, when it's running, how much memory you need, rather than having to decide when WRITING the program.
Edit: It is generally best to "hide" any memory allocation using the already existing "container-" and "wrapper-classes" that are useful for this very purpose. For example:
would work as a variable storage for integers, and you never have to worry about freeing the memory, or even knowing how many you need before you have stored them there.
is another case, where when the "shared_ptr" is no longer in use [it track that inside the shared pointer class, so you never need to care about freeing the memory].
[1] If you don't want to leak memory, and it's "bad style" to leak memory. Not making anyone happy if you do.
I've seen many posts about memory allocation in C++, questions about "new operator" vs "operator new", questions about
new int(100)
vsnew 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:
<cstdlib>
), we have mainlymalloc
andcalloc
andfree
. I won't talk aboutrealloc
.<new>
), we have:new T( args )
new (std::nothrow) T( args )
delete ( T* )
new T[ size_t ]
new (std::nothrow) T[ size_t ]
delete[] ( T* )
new (void*) T( args )
new (void*) T[ size_t ]
::operator new( size_t )
;::operator new( size_t, std::nothrow )
;::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 usingsizeof
).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 usingfree
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, alldelete
-statements take fully typed pointers, somenew
-statements return fully-typed pointers, somenew
-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 containnew
either as a function or keyword. People also talk about "new
-expressions", wherenew
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).
::operator new( size_t )
and::operator new( size_t, std::nothrow )
take a size in bytes, and return avoid*
in case of success.std::bad_alloc
, the latter returnsNULL
.::operator new( sizeof(T) )
for a single object of typeT
(anddelete
for release), and::operator new( n*sizeof(T) )
for multiple objects (anddelete[]
for release).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
ordelete[]
.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 eitherdelete
ordelete[]
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 typeT
and sizen
.Then
::operator new( n*sizeof(T), (T*) ptr )
initializesn
elements of typeT
starting fromptr
using the default constructorT::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 typeT
using the constructorT::T( args )
. The default constructor will not be called unless arguments are omitted (ienew T()
or evennew T
). Throws an exceptionstd::bad_alloc
on failure.new (std::nothrow) T( args )
except that it returnsNULL
in case of failure.delete
to call the destructorT::~T()
and release the corresponding memory.Multiple-objects allocation & initialization
new T[n]
allocates and initializes memory for an
objects of typeT
using the default constructor. Throws an exceptionstd::bad_alloc
on failure.new (std::nothrow) T[n]
except that it returnsNULL
in case of failure.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 constructorT::T(args)
on the memory stored atptr
. The default constructor is not called unless arguments are omitted.new (ptr) T[n]
calls the default constructorT::T()
onn
objects of typeT
stored fromptr
toptr+n
(ie,n*sizeof(T)
bytes).Related posts