new

From Cppwiki

Jump to: navigation, search

The new keyword is used to construct one or more objects of a particular type. It has two forms:

  • new - Construct a single object
  • new[] - Construct one or more objects, specified through a count value between the brackets

Unless the placement new syntax is used, the new keyword also preallocates space for the objects it constructs. This is done using the operator new functions, which allocate raw, uninitialized memory from the free store.


Contents

Usage

Both forms of new return a pointer to an allocated block of memory. In the case of operator new, a pointer to a single object is returned; the pointer from new[], obviously, points to an array. The usage is:

T* my_t_ptr = new T;
T* my_t_array = new T[size];

Using new

Generally it is preferred to avoid direct memory management, in favor of RAII. In the case where you absolutely have to manage allocation and deallocation yourself, care needs to be taken to use new properly. Careless use of new can lead to memory leaks and heap corruption. The differences between the two forms of new are outlined below.

new

With the single operator new you only create one object at a time. The benefit to this is that you can specify class constructors when using this type of new. If, for instance, you were creating a new string, and you wanted to initialize it with the value "This is my string", it would look like:

std::string* my_string = new std::string("This is my string");

If only the type is given, with no arguments for a constructor, the default constructor is called.

Alternatives to solutions involving new

RAII (including standard containers) should generally be used in the place of direct memory management. In the case of a single object being handled by a pointer, a smart pointer can be used instead.

new[]

In contrast, with array new you cannot specify any arguments to constructors. When allocating arrays with new, the default constructor is called for every object. This is problematic if you have a class that has no default constructor, and you're unable to provide one.

std::string* my_strings = new std::string[size];

Alternatives to solutions involving new[]

As previously mentioned, RAII is usually favored above the use of new. A common container class that is preferred above new[] is std::vector which handles allocation and deallocation automatically, and with some usage allows you to specify how elements are created.

Deallocation

Main article: delete

It's important to use the correct form of delete when you're ready to free memory allocated with new. Unlike objects placed on the stack the memory isn't released for you automatically, and no destructors are ever called unless you delete the pointers you've allocated. Failure to use the correct form of delete results in undefined behavior.

Keyword new vs. operator new

The execution of a new expression is easiest explained as a two phase process. When new, or new[], is invoked, the first action taken is the allocation of the memory required; this falls under the auspices of operator new. Because new is an operator, it can be overloaded -- unlike most operators, however, new can also be overloaded at the global scope.

An example of how a (global) new overload might look:

#include <new>
#include <cstdlib>

void* operator new(std::size_t size) throw (std::bad_alloc)
{
        if (!size)
        {
                size = 1;
        }

        void* p = 0;
        while (!(p = std::malloc(size)))
        {
                new_handler nh = std::set_new_handler(0); // There is no other way to get the new_handler
                std::set_new_handler(nh);

                if (!nh)
                {
                        throw std::bad_alloc();
                }

                nh();
        }
        return p;
}

When overloading operator new, because the underlying allocation method has changed, it's imperitive that you also write a corresponding operator delete. Also note that operator new is different from operator new[], though the code for each overload (not provided) may appear similar. By extension, operator delete is unique from operator delete[]. This applies at both the global, and class levels.

Keyword new

One thing conspicuously absent from the above example is the invokation of a constructor. The 'keyword new' functionality is unique from the operator new functionality. Where operator new, or operator new[], are responsible for allocation of memory, keyword new is responsible for invoking constructors for all objects created. This applies to single objects, as well as arrays, and the behavior of the new keyword can not be changed.

Placement new

Placement new is a special form of new. It is the converse of operator new; it does not allocate any memory, but instead invokes constructors on already allocated memory. For instance,

T *t = new T(42);

Could instead be written:

T *t = ::operator new(sizeof(T));
new (t) T (42);

The (t) syntax provides the location of the already allocated memory where the object should be constructed.

The reverse of placement new is an explicit destructor invokation:

t->~T();
::operator delete(t);

Placement new actually works by invoking a special variant of operator new:

void *operator new(std::size_t, void *p) throw() {
  return p;
}

nothrow

Another special variant of operator new is

void *operator new(std::size_t, const std::nothrow_t &) throw();

This is invoked using the global object std::nothrow:

T *t = new (std::nothrow) T(42);

The nothrow version of operator new will return NULL on allocation failure, instead of throwing std::bad_alloc.

Personal tools