Show how to explicitly allocate and deallocate blocks of memory in your language. Show access to different types of memory (i.e., heap, stack, shared, foreign) if applicable.
While the C allocation functions are also available in C++, their use is discouraged. Instead, C++ provides new
and delete
for memory allocation and deallocation. Those function don’t just allocate memory, but also initialize objects. Also, deallocation is coupled with destruction.
#include <string> int main() { int* p; p = new int; // allocate a single int, uninitialized delete p; // deallocate it p = new int(2); // allocate a single int, initialized with 2 delete p; // deallocate it std::string* p2; p2 = new std::string; // allocate a single string, default-initialized delete p2; // deallocate it p = new int[10]; // allocate an array of 10 ints, uninitialized delete[] p; // deallocation of arrays must use delete[] p2 = new std::string[10]; // allocate an array of 10 strings, default-initialized delete[] p2; // deallocate it }
Note that memory allocated with C allocation functions (malloc
, calloc
, realloc
) must always be deallocated with free
, memory allocated with non-array new
must always be deallocated withdelete
, and memory allocated with array new
must always deallocated with delete[]
. Memory allocated with new also cannot be resized with realloc
.
Note that use of the array form is seldom a good idea; in most cases, using a standard container (esp. std::vector
) is a better idea, because it manages the memory for you, it allows you to define an initial value to set in the array (new[] always default-initializes), and like malloc, but unlike array new, it allows resizing (and unlike realloc, it correctly handles construction/destruction when resizing).
Besides the new expressions shown above, pure memory allocation/deallocation without object initialization/destruction can also be done through operator new
:
int main() { void* memory = operator new(20); // allocate 20 bytes of memory operator delete(memory); // deallocate it }
There’s also a placement form of new, which allows to construct objects at an arbitrary adress (provided it is correctly aligned, and there’s enough memory):
#include <new> int main() { union { int alignment_dummy; // make sure the block is correctly aligned for ints char data[2*sizeof(int)]; // enough space for 10 ints }; int* p = new(&data) int(3); // construct an int at the beginning of data new(p+1) int(5); // construct another int directly following }
Indeed, code like int* p = new int(3);
is roughly (but not exactly) equivalent to the following sequence:
void* memory_for_p = operator new(sizeof(int)); int* p = new(memory_for_p) int(3);
Normally, new throws an exception if the allocation fails. there’s a non-throwing variant which returns a null pointer instead:
#include <new> int* p = new(std::nothrow) int(3);
Note that the nothrow variant does not prevent any exceptions to be thrown from the constructor of an object created with new. It only prevents exceptions due to memory allocation failure.
It is also possible to implement user-defined variations of operator new. One possibility is to define class-based operator new/operator delete:
#include <cstddef> #include <cstdlib> #include <new> class MyClass { public: void* operator new(std::size_t size) { void* p = std::malloc(size); if (!p) throw std::bad_alloc(); return p; } void operator delete(void* p) { free(p); } }; int main() { MyClass* p = new MyClass; // uses class specific operator new delete p; // uses class specific operator delete int* p2 = new int; // uses default operator new delete p2; // uses default operator delete }
Another possibility is to define new arguments for placement new syntax, e.g.
class arena { /* ... */ }; void* operator new(std::size_t size, arena& a) { return arena.alloc(size); } void operator delete(void* p, arena& a) { arena.dealloc(p); } arena whatever(/* ... */); int* p = new(whatever) int(3); // uses operator new from above to allocate from the arena whatever
Note that there is no placement delete syntax; the placement operator delete is invoked by the compiler only in case the constructor of the newed object throws. Therefore for placement newed object deletion the two steps must be done explicitly:
class MyClass { /*...*/ }; int main() { MyClass* p = new(whatever) MyClass; // allocate memory for myclass from arena and construct a MyClass object there // ... p->~MyClass(); // explicitly destruct *p operator delete(p, whatever); // explicitly deallocate the memory }
Content is available under GNU Free Documentation License 1.2.