views:

264

answers:

4

i came across this line is stroustrup An operator function must either be a member or take at least one argument of a user-defined type (functions redefining the new and delete operators need not).

Dont operator new and operator delete take an user defined type as one of their arguments? what does it mean, am i missing something here

+3  A: 

You can overload the normal global new operator, for all classes to add functionality (e.g. logging or leak detection) if you so desire, but there's no way to call the old definition of the new operator, so you'll probably be stuck calling malloc() from inside your redefined operator new to actually get the memory that you need.

Ken Bloom
If this would overloading (or even overriding) then there would be a way to call the original global `new`. It's not overloading.
wilhelmtell
It's actually replacement and not overloading, so once you've provided your own `new`/`delete` there's no way to call the "original" ones.
Andreas Brinck
+4  A: 

The quote from Stroustrup apparently applies to operator overloading. C++ language supports operator overloading for user-defined types only. This means that the overloading function (operator <something>) has to be either a member of user-defined type or be a standalone function with at least one argument of user-defined type. This is exactly what is meant by the quote in question.

Yet standalone (non-member) operator new and operator delete functions are not required to take a value of user defined type as one of their arguments. This might be seen as something that contradicts your quote.

However, in reality there's no contradiction. These operators are not really overloaded. When you provide your own versions of standalone operator new/operator delete, you are actually replacing the library-provided ones. This is the official term from the language specification: replacement, not overloading. Which is why the above quote does not really apply to operator new and operator delete.

AndreyT
Potatoswatter
Yes, but what I meant is that you *can* write your own version of "standard" `operator new`: `void * operator new(size_t)`. This one will seemingly violate the requirement present in the quote. Yet this is legal.
AndreyT
@Andrey: Sorry, `my_sandbox` is a red herring. `void *operator new(size_t, int)` is an overload too. Also "search path" is poor phrasing. `operator new` is looked up in class scope, using overloading rules, which falls through to global scope, where the user may have a replacement to the default. My point is that *both* overloading and replacement happen. By the way, do you see anything wrong with my answer?
Potatoswatter
@Potatoswatter: OK, you are right about `void *operator new(size_t, int)`. It is overloading. It is probably safe to conclude that `operator new` and `operator delete` are "special". In fact, I remember arguing here on SO that these two are not really true operators, but rather special functions that just happen to use syntax that looks like operator overloading.
AndreyT
You probably quoted §13.5/5, which says essentially that any similarity besides in name is pure coincidence :v) .
Potatoswatter
A: 

operator new and operator delete are looked up based on the type of the operand in the new or delete expression, and any extra parenthetical arguments to new. Thus they may be overloaded (and operator new is subject to overload resolution), but by a different mechanism than the other operators. (C++03 §13.5/5)

As they work with raw memory, they never deal with pointers to the client class type. operator new always takes a size_t argument (and possibly other arguments, none of which need be of user-defined type) and returns void *. operator delete always takes a void * argument and optionally a size_t, no matter how it was looked up.

I can think of two reasons for this:

  • They deal with raw memory, not containing a constructed object. It is always an error for operator new or operator delete to attempt to access an object within the returned block of memory. (Memory not used to construct objects, however, is fair game.)
  • A class member operator new or operator delete may be multiply- and/or virtually-inherited, such that the void* in question cannot be made to point to the not-yet-constructed or already-destroyed subobject, by any voodoo.
Potatoswatter
Explain downvote?
Potatoswatter
It's not quite clear how it answers the actual question, despite discussing relevant related areas. I would never have downvoted, but also wouldn't have upvoted either.
Donal Fellows
I suppose I don't cut right to the point, but I do directly address how and why they get overloaded without user-defined type arguments. I see that as the central question… maybe I'm missing something there.
Potatoswatter
A: 

a + b is just syntactic sugar for a.operator+(b) or operator+(a, b).

On the other hand, new Foo(x, y, z) is NOT just syntactic sugar for operator new(Foo, x, y, z) or something like that. It is way more complicated:

void* address = operator new(sizeof(Foo)); // here is the behavior you can replace
try {
    new(address) Foo(x, y, z);
} catch (...) {
    operator delete(address);
}

As you can see, the function operator new merely allocates memory, which is only half of what the operator new actually does. In my opinion, it would have made far more sense to have named that thing allocate_memory or something like that. It definitely IS NOT an operator like operator+.

FredOverflow