[comp.lang.c++] Class-specific operator new

sdm@cs.brown.edu (Scott Meyers) (12/15/89)

I think I've found a bug in CC's handling of class-specific definitions of
operator new.  The following compiles:

    #include <new.h>
    void *operator new(size_t size, void *location){ return location; }
    class C {
      char storage[10];
    public:
      C() { new (storage) int; }
      };

But if I move the definiton of operator new inside the class, it won't
compile: 

    #include <new.h>
    class C {
      char storage[10];
    public:
      void *operator new(size_t size, void *location){ return location; }
      C() { new (storage) int; }
      };

The error is:

    error:  argument  2 of type void * expected for C::operator new

Bona fide bug, or pilot error?


Scott
sdm@cs.brown.edu

landauer@morocco.Sun.COM (Doug Landauer) (12/16/89)

Scott Meyers asks a reasonable question:
> I think I've found a bug in CC's handling of class-specific definitions of
> operator new.  The following compiles:
> 
>     #include <new.h>
>     void *operator new(size_t size, void *location){ return location; }
>     class C {
>       char storage[10];
>     public:
>       C() { new (storage) int; }
>       };

OK, here you have *almost* redefined the global operator new.
You've *overloaded* it with another "new" function which takes
an extra argument.  The original (libC) "new" is used whenever
you say "new thing", and yours is used whenever you say
"new (location) thing".   As you might expect.

> But if I move the definiton of operator new inside the class, it won't
> compile: 
> 
>     #include <new.h>
>     class C {
>       char storage[10];
>     public:
>       void *operator new(size_t size, void *location){ return location; }
>       C() { new (storage) int; }
>       };

Here, you seem to expect C::new to be called for the new int.  This is
not what class-specific operator new is used for.   Instead, your
class-specific "new" is to be used anywhere that any "C" is dynamically
allocated.  (That's why it's called "class-specific operator new"
rather than "member new" or some such.)  That's still not enough to
confuse things, until you realize that CC inserts some extra code at
the start of each constructor.  You can't read the code very well,
because your C::C() constructor is in-line (try these examples with a
"+d" argument to out-line them), but what this code does is to allocate
a new "this" if the constructor is entered with "this" == 0.  The code
looks roughly like this (no pun intended):

	if( this ||
	   (this = (C*)(C::operator new(sizeof(C)))) != 0
	  )
	{
	    *** The body of your constructor ***
	}

	return this;

That is, if the constructor is called with this==0, it will call
"C::operator new" with only the size argument.  (See section B.3.3 of
the C++ reference manual for a description of why it does this stuff.)
*THAT HIDDEN LINE* is what is generating the error message:

> error:  argument  2 of type void * expected for C::operator new
> Bona fide bug, or pilot error?

The error message is technically correct, but exceptionally unhelpful.
What it "meant" to say was

     error:  C::C must call C::operator new (size_t), but there isn't one

So, in order to get your example to compile, you could add another
C::operator new, which doesn't demand the second argument:

	#include <new.h>
	class C {
	    char storage[10];
	public:
	    void *operator new(size_t size){ return ::new C; }
	    void *operator new(size_t size, void *location){ return location; }
	    C() { new (storage) int; }
	};

But note that neither of your "C::operator new" functions will be
called by the "new (storage) int" statement.
-- 
  Doug Landauer -- landauer@eng.sun.com   or   ...!sun!landauer   _
  Sun Microsystems, Inc. -- SPD, SET, Languages                  La no ka 'oi.