When talking about new there are two distinct parts: the operator new, and the function operator new(). The last time I went over this with somebody, it took them ages to get it. What happens is that the operator new calls the function operator new() to allocate memory. The function operator new() acts just like malloc, it's a general memory manager that takes memory from a pool and doles it out to the program as requested. Just like malloc, operator new() also handles fragmentation issues and the like. Everything you learned about malloc applies to operator new().

The comes the operator new. Once it has the memory that it needs, operator new will then proceed to handle basic construction maintenance including--but not always limited to--calling constructors for the object to be created. You can think of operator new() as allocate_memory() and operator new as initialize_memory(). Operator new is the one that determines how much memory is needed (such as the space for a virtual table if the object is polymorphic) based on the type of object being created, operator new is the one that partitions the new memory as needed (such as any housekeeping data for the object that only the compiler knows about), operator new is the one that makes sure the memory is initialized before being used (such as calling the object's constructor). Once the constructor is called, it takes over further partitioning and initializing of the memory because operator new doesn't know the layout of the object.

function operator new() works in the same way as malloc. The only reason malloc isn't actually used is to avoid the overhead of calling the function (or the considerable overhead of malloc itself), so standard implementations of operator new() will basically do the same thing as malloc without calling malloc itself and attempt to optimize the algorithm chosen as much as possible.

Every implementation in different compiler that I've seen does it differently, but the operations are the same: dole out memory from a pool and rearrange the pool when possible to avoid fragmentation.

Comments: new操作符和new操作符函数是不一样的,new操作符要使用new操作符函数分配内存,并采用适当的算法避免内存碎片。那如何证明new操作符和new操作符函数是不一样的呢?下面引用自MSDN:How new Works 。注意下文中加黑体的短语是一个整体。

 The allocation-expression — the expression containing the new operator — does three things:

  • Locates and reserves storage for the object or objects to be allocated. When this stage is complete, the correct amount of storage is allocated, but it is not yet an object.
  • Initializes the object(s). Once initialization is complete, enough information is present for the allocated storage to be an object.
  • Returns a pointer to the object(s) of a pointer type derived from new-type-name or type-name. The program uses this pointer to access the newly allocated object.

The new operator invokes the function operator new. For arrays of any type, and for objects that are not of class, struct, or union types, a global function, ::operator new, is called to allocate storage. Class-type objects can define their own operator new static member function on a per-class basis.

When the compiler encounters the new operator to allocate an object of type type, it issues a call to type::operator new( sizeof( type ) ) or, if no user-defined operator new is defined, ::operator new( sizeof( type ) ). Therefore, the new operator can allocate the correct amount of memory for the object.

Note   The argument to operator new is of type size_t. This type is defined in DIRECT.H, MALLOC.H, MEMORY.H, SEARCH.H, STDDEF.H, STDIO.H, STDLIB.H, STRING.H, and TIME.H.

An option in the grammar allows specification of placement (see the Grammar for new Operator). The placement parameter can be used only for user-defined implementations of operator new; it allows extra information to be passed to operator new. An expression with a placement field such as

T *TObject = new ( 0x0040 ) T;

is translated to

T *TObject = T::operator new( sizeof( T ), 0x0040 );

The original intention of the placement field was to allow hardware-dependent objects to be allocated at user-specified addresses.

Note   Although the preceding example shows only one argument in the placement field, there is no restriction on how many extra arguments can be passed to operator new this way.

Even when operator new has been defined for a class type, the global operator can be used by using the form of this example:

T *TObject =::new TObject;

The scope-resolution operator (::) forces use of the global new operator.