7.6 Dynamic Memory: new and delete
Memory regions and why the heap is needed
At run time, memory is split into several regions: the code region (instructions), the data region (global and static variables), the stack (local variables, allocated and freed automatically by the compiler), and the heap (allocated and freed manually by the programmer).
A local array on the stack is freed when the function returns, so you must not return its address to the caller. Also, once an array is declared, its size is fixed. When the array size is decided at run time, or the data must outlive the function that creates it, you allocate memory dynamically on the heap.
new and delete
In C++, new allocates an object on the heap and returns a typed pointer. new[] allocates an array. When you are done, release a single object with delete and an array with delete[]; otherwise you cause a memory leak.
int *arr = new int[n];
// ... use arr ...
delete[] arr; // release when doneIf you want an allocation failure to return nullptr instead of throwing an exception, use std::nothrow.
#include <new>
int *arr = new (std::nothrow) int[n];
if (arr == nullptr) {
return 1; // allocation failed
}Initialization and resizing
new int[n] does not initialize every element to a known value. new int[n]() value-initializes the elements, so integers become 0.
int *arr = new int[n](); // all zerosRaw arrays allocated with new[] cannot be resized directly. To grow one manually, allocate a new array, copy the old values, delete the old array, and then keep the new pointer.
int *next = new int[new_size];
for (int i = 0; i < old_size; i++) {
next[i] = arr[i];
}
delete[] arr;
arr = next;The function below builds a Fibonacci sequence on the heap and returns it; the caller is responsible for delete[] when done:
int *generate_fibonacci(int n) {
int *arr = new (std::nothrow) int[n];
if (arr == nullptr) {
return nullptr;
}
arr[0] = 1;
arr[1] = 1;
for (int i = 2; i < n; i++) {
arr[i] = arr[i - 1] + arr[i - 2];
}
return arr;
}Be especially careful with dynamic memory: check for nullptr when using std::nothrow, avoid going out of bounds, avoid double deletes, and never use an old pointer after delete.