1.15.2.  Operators new and delete

[ fromfile: pointers.xml id: newdelete ]

C++ has a mechanism that permits storage to be allocated dynamically at runtime. This means that the programmer does not need to anticipate the memory needs of a program in advance and make allowances for the maximum amount of memory that might be needed by the program. Dynamic allocation of storage at runtime is a powerful tool that helps to build programs that are efficient and flexible.

The new operator allocates storage from the heap (also known as dynamic storage) and returns a pointer to the newly allocated object. If for some reason it is not possible for the memory to be allocated, an exception is thrown.[21]

The delete operator releases dynamically allocated memory and returns it to the heap. delete should be applied only to pointers returned by new, or to null pointers. Heap memory that is no longer needed should be released for reuse. Failure to do so can result in crippling memory leaks.

In general, the code that calls new should document, or be physically located near, the code that frees the memory. The goal is to keep memory management code as simple and reliable as possible.

Dereferencing a null, deleted, or uninitialized pointer causes a runtime error, usually a segmentation fault or, in Windows, a general protection fault (GPF). It is the responsibility of the programmer to make sure that this cannot happen. We will discuss techniques to ensure that such errors are avoided.

The syntax of the new and delete operators is demonstrated in the code fragment shown in Example 1.28.

Example 1.28. src/pointers/newdelete/ndsyntax.cpp

#include <iostream>
using namespace std;

int main() {
 int* ip = 0;               1
 delete ip;                 2
 if(ip) cout << "non-null" << endl;
 else cout << "null" << endl;
 ip = new int;              3
 int* jp = new int(13);     4
 //[...]      
 delete ip;                 5
 delete jp;
}

1

null pointer

2

has no effect at all - ip is still null.

3

allocate space for an int

4

allocate and initialize

5

Without this, we have a memory leak.


Null pointers are actually quite useful in programs. Even though it is a fatal runtime error to attempt to dereference a null pointer, it is perfectly legal to check to see if a pointer is null. For example, it is common practice for a function to search for an item in a container of pointers and, if the search is successful, returns a pointer to that item. If the search is not successful, it still must return a pointer. In that case, returning a null pointer is a good choice. Of course, you must be careful to check the return value of such a function before dereferencing it to make sure it is not null. After a pointer has been deleted, assignment is the only legal operation that can be performed with it. We recommend immediately assigning the value 0 to a deleted pointer if no other choice is feasible.

[Note] Note

Qt, the Standard Library, and Boost.org each provide a variety of classes and functions to help manage and clean up heap memory. In addition to container classes, each library has one or more smart pointer class(es). A smart pointer is an object that stores and manages a pointer to a heap object. It behaves much like an ordinary pointer except that it automatically deletes the heap object at the appropriate time. Qt has QPointer, the standard library has std::auto_ptr, and Boost has a shared_ptr. Using one of these classes makes C++ memory management much easier and safer than it used to be.



[21] We discuss this situation in an article on our Website.