4

I understand that there are 3 general ways to modify the behaviour of new and delete in C++:

  • Replacing the default new/delete and new[]/delete[]
  • Overriding or overloading the placement versions (overriding the one with a memory location passed to it, overloading when creating versions which pass other types or numbers of arguments)
  • Overloading class specific versions.

What are the restrictions for performing these modifications to the behaviour of new/delete?

In particular are there limitations on the signatures that new and delete can be used with?

It makes sense if any replacement versions must have the same signature (otherwise they wouldn't be replacement or would break other code, like the STL for example), but is it permissible to have global placement or class specific versions return smart pointers or some custom handle for example?

Community
  • 1
  • 1
Bingo
  • 3,785
  • 6
  • 23
  • 27
  • 1
    Related & might be useful: [How should I write ISO C++ Standard conformant custom new and delete operators?](http://stackoverflow.com/questions/7194127/how-should-i-write-iso-c-standard-conformant-custom-new-and-delete-operators) – Alok Save Jan 06 '12 at 06:30

2 Answers2

4

First off, don't confuse the new/delete expression with the operator new() function.

The expression is a language construct that performs construction and destruction. The operator is an ordinary function that performs memory (de)allocation.

Only the default operators (operator new(size_t) and operator delete(void *) can be used with the default new and delete expressions. All other forms are summarily called "placement" forms, and for those you can only use new, but you have to destroy objects manually by invoking the destructor. Placement forms are of rather limited and specialised need. By far the most useful placement form is global placement-new, ::new (addr) T, but the behavior of that cannot even be changed (which is presumably why it's the only popular one).

All new operators must return void *. These allocation functions are far more low-level than you might appreciate, so basically you "will know when you need to mess with them".

To repeat: C++ separates the notions of object construction and memory allocation. All you can do is provide alternative implementations for the latter.

Kerrek SB
  • 464,522
  • 92
  • 875
  • 1,084
  • It is good to understand that allocation and construction are separate tasks.. And so the regular use of the new keyword performs allocation and construction, while the placement new form only performs construction? So I guess all placement forms need to have a void * to know where to construct the object? or for the compiler to know where to construct the object? If placement versions of new are being told where to construct, do they still need to return a void *? – Bingo Jan 06 '12 at 11:58
  • Only the global default placement-new (`::operator new(size_t, void *)`) is guaranteed to be a no-op. Other placement-forms, as well as class member functions, may do whatever they like. Every form of the new-operator must return a `void *`, which becomes the object's `this` pointer. – Kerrek SB Jan 06 '12 at 12:53
  • Right, I think I am getting it better now. So only the default global placement new is guaranteed not to allocate, but any custom ones.. well they are custom and may or may not allocate. But they all return void * and the compiler takes this void *, makes it *this and calls the constructor to construct the object at that memory location. Is this right? The conclusion I am drawing is that no overloaded new operator calls the constructor explicitly, it is all done by the compiler after operator new performs the 'allocation'. – Bingo Jan 06 '12 at 13:10
  • @Bingo: That's right. In a sense, global-default-placement-new is the *only* way you can reliably "call" a constructor manually and do nothing else. – Kerrek SB Jan 06 '12 at 13:29
0

When you overload new and delete within a class you are effectively modifying the way the memory is allocated and released for the class, asking for it to give you this control.

This may be done when a class wants to use some kind of pool to allocate its instances, either for optimisation or for tracking purposes.

Restrictions, as with pretty much any operator overload, is the parameter list you may pass, and the behaviour it is expected to adhere to.

CashCow
  • 30,981
  • 5
  • 61
  • 92
  • Yes, "restrictions...[are] the parameter list you may pass, and the behaviour it is expected to adhere to." The standard behaviour is outlined in the link posted against the question, but what parameter list must I pass? If it is pretty much like other operators, I could do anything. And what return type can it be? – Bingo Jan 06 '12 at 11:38