Reputation: 170509
Looks like operator new
and operator new[]
have exactly the same signature:
void* operator new( size_t size );
void* operator new[]( size_t size );
and do exactly the same: either return a pointer to a big enough block of raw (not initialized in any way) memory or throw an exception.
Also operator new
is called internally when I create an object with new
and operator new[]
- when I create an array of objects with new[]
. Still the above two special functions are called by C++ internally in exactly the same manner and I don't see how the two calls can have different meanings.
What's the purpose of having two different functions with exactly the same signatures and exactly the same behavior?
Upvotes: 12
Views: 882
Reputation: 552
In Design and Evolution of C++ (section 10.3), Stroustrup mentions that if the new operator for object X was itself used for allocating an array of object X, then the writer of X::operator new() would have to deal with array allocation too, which is not the common usage for new() and add complexity. So, it was not considered to use new() for array allocation. Then, there was no easy way to allocate different storage areas for dynamic arrays. The solution was to provide separate allocator and deallocator methods for arrays: new[] and delete[].
Upvotes: 7
Reputation: 279345
One purpose is that they can be separately defined by the user. So if I want to initialize memory in single heap-allocated objects to 0xFEFEFEFE and memory in heap-allocated arrays to 0xEFEFEFEF, because I think it will help me with debugging, then I can.
Whether that's worth it is another matter. I guess if your particular program mostly uses quite small objects, and quite large arrays, then you could allocate off different heaps in the hope that this will reduce fragmentation. But equally you could identify the classes which you allocate large arrays of, and just override operator new[]
for those classes. Or operator new
could switch between different heaps based on the size.
There is actually a difference in the wording of the requirements. One allocates memory aligned for any object of the specified size, the other allocates memory aligned for any array of the specified size. I don't think there's any difference - an array of size 1 surely has the same alignment as an object - but I could be mistaken. The fact that by default the array version returns the same as the object version strongly suggests there is no difference. Or at least that the alignment requirements on an object are stricter than those on an array, which I can't make any sense of...
Upvotes: 5
Reputation: 99665
Standard says that new T
calls operator new( )
and new T[ ]
results in a call of operator new[]( )
. You could overload them if you want. I believe that there is no difference between them by default. Standard says that they are replaceable (3.7.3/2):
The library provides default definitions for the global allocation and deallocation functions. Some global allocation and deallocation functions are replaceable (18.4.1). A C + + program shall provide at most one definition of a replaceable allocation or deallocation function. Any such function definition replaces the default version provided in the library (17.4.3.4). The following allocation and deallocation functions (18.4) are implicitly declared in global scope in each translation unit of a program
void* operator new(std::size_t) throw(std::bad_alloc); void* operator new[](std::size_t) throw(std::bad_alloc); void operator delete(void*) throw(); void operator delete[](void*) throw();
Upvotes: 1
Reputation: 792777
I've had a reasonably good look at this, and to be blunt there's no reason from an interface standpoint.
The only possible reason that I can think of is to allow an optimization hint for the implementation, operator new[]
is likely to be called upon to allocate larger blocks of memory; but that is a really, really tenuous supposition as you could new
a very large structure or new char[2]
which doesn't really count as large.
Note that operator new[]
doesn't add any magic extra storage for the array count or anything. It is the job of the new[]
operator to work out how much overhead (if any) is needed and to pass the correct byte count to operator new[]
.
[A test with gcc indicates that no extra storage is needed by new[]
unless the type of the array members being constructed have a non-trivial desctructor.]
From an interface and contract standpoint (other than require the use of the correct corresponding deallocation function) operator new
and operator new[]
are identical.
Upvotes: 7
Reputation: 254681
The operators can be overridden (for a specific class, or within a namespace, or globally), and this allows you to provide separate versions if you want to treat object allocations differently from array allocations. For example, you might want to allocate from different memory pools.
Upvotes: 7