[comp.lang.c++] operator new

nmyers@mntgfx.mentor.com (Nathan Myers) (06/08/89)

Providing arguments for operators new() and delete() is a major
advance.  It offers more power than "this=" semantics, and allows
smaller, faster code.  However,

ark@alice.UUCP (Andrew Koenig) writes
> Operator new (and operator delete) obeys the same scope rules as any
> other member function: if defined inside a class, operator new hides
> any global operator new.  For example:
> 
> 	class T {
> 	/* stuff */
> 	public:
> 		void* operator new(size_t, Memory_speed);
> 	/* more stuff */
> 	};
> 
> 	T* tp = new T;		// Error!
> 
> The use of `new T' is incorrect in this example because the member
> operator new hides the global operator new, so no operator new
> can be found for T that does not require a second argument.

This seems inconsistent to me.  Other overloaded functions don't
hide their neighbors, why should operator new()?  The standard way
to hide a global is to declare a member with the same name and arguments.
Then, if I (as class T author) want to disallow ::operator new(size_t),
I can declare a private one and not define it.

A self-consistent alternative to the posted semantics is:
1. Member operator new(size_t, class Foo) doesn't hide global ::new(size_t).
2. Member operator new(size_t) may be declared private.
3. "::new T" is not valid syntax.  (It seems unnecessary, and dangerous.)

Nathan Myers
nmyers@pdx.mentor.com

rfg@pink.ACA.MCC.COM (Ron Guilmette) (06/10/89)

In article <1989Jun7.115321.22620@mntgfx.mentor.com> nmyers@mntgfx.mentor.com (Nathan Myers) writes:
^ >Providing arguments for operators new() and delete() is a major
^ >advance.  It offers more power than "this=" semantics, and allows
^ >smaller, faster code.  However,

... [ problems ] ...

^ >This seems inconsistent to me.  Other overloaded functions don't
^ >hide their neighbors, why should operator new()?  The standard way
^ >to hide a global is to declare a member with the same name and arguments.
^ >Then, if I (as class T author) want to disallow ::operator new(size_t),
^ >I can declare a private one and not define it.
^ >
^ >A self-consistent alternative to the posted semantics is:
^ >1. Member operator new(size_t, class Foo) doesn't hide global ::new(size_t).
                                                               ^^^^^^^^^^^^^

Do you mean ::operator new(size_t) ?

^ >2. Member operator new(size_t) may be declared private.
^ >3. "::new T" is not valid syntax.  (It seems unnecessary, and dangerous.)
    ^^^^^^^^

Did you mean ::operator new T  ?


-- 
// Ron Guilmette  -  MCC  -  Experimental Systems Kit Project
// 3500 West Balcones Center Drive,  Austin, TX  78759  -  (512)338-3740
// ARPA: rfg@mcc.com
// UUCP: {rutgers,uunet,gatech,ames,pyramid}!cs.utexas.edu!pp!rfg

ark@alice.UUCP (Andrew Koenig) (06/10/89)

In article <242@pink.ACA.MCC.COM>, rfg@pink.ACA.MCC.COM (Ron Guilmette) writes:
> In article <1989Jun7.115321.22620@mntgfx.mentor.com> nmyers@mntgfx.mentor.com (Nathan Myers) writes:

> ^ >A self-consistent alternative to the posted semantics is:
> ^ >1. Member operator new(size_t, class Foo) doesn't hide global ::new(size_t).
>                                                                ^^^^^^^^^^^^^
> 
> Do you mean ::operator new(size_t) ?
> 
> ^ >2. Member operator new(size_t) may be declared private.
> ^ >3. "::new T" is not valid syntax.  (It seems unnecessary, and dangerous.)
>     ^^^^^^^^
> 
> Did you mean ::operator new T  ?

I guess it's time for me to jump in again.

An example:

	class T {
	public:
		void* operator new(size_t);
		void operator delete();
		// other stuff
	};

	void f()
	{
		T* tp1 = new T;		// calls T::operator new
		T* tp2 = ::new T;	// calls ::operator new
		T* tp3 = T[10];		// calls ::operator new
		delete tp1;		// calls T::operator delete
		::delete tp2;		// calls ::operator delete
		delete[10] tp3;		// calls ::operator delete
	}

When you say `new T' it looks for `operator new' using the usual
scope rules as if you were in the definition of a member function
of T.  That is: it first looks for T::operator new, then it searches
the base class(es) of T, and finally it looks in the global scope.
When you say `::new T' it skips T and all its base classes and
goes straight to the global scope.

Most people will never use ::new or ::delete; that's why they have
a funny kind of syntax.  They are there to help authors of container
classes.  For example, suppose you're writing an array-like class
that will contain objects of arbitrary type.  Once C++ gets templates,
that will be easy, but even now it can be done reasonably effectively
through the C preprocessor.

Now, suppose you've written a class T and I want to make a container
that contains T objects?  My container had better control the memory
allocation for the objects it contains, so that it can free the objects
when the container itself is freed.

But how can the container control memory allocation for T if T
itself controls its memory allocation?  Evidently we need a mechnism
for overriding a class' request to control its own memory.
That is the purpose of ::new and ::delete.
-- 
				--Andrew Koenig
				  ark@europa.att.com

shopiro@alice.UUCP (Jonathan Shopiro) (06/14/89)

In article <1989Jun7.115321.22620@mntgfx.mentor.com>, nmyers@mntgfx.mentor.com (Nathan Myers) writes:
> Providing arguments for operators new() and delete() is a major
> advance.  It offers more power than "this=" semantics, and allows
> smaller, faster code.  However,
> 
> ark@alice.UUCP (Andrew Koenig) writes
> > Operator new (and operator delete) obeys the same scope rules as any
> > other member function: if defined inside a class, operator new hides
> > any global operator new.  For example:
> > 
> > 	class T {
> > 	/* stuff */
> > 	public:
> > 		void* operator new(size_t, Memory_speed);
> > 	/* more stuff */
> > 	};
> > 
> > 	T* tp = new T;		// Error!
> > 
> > The use of `new T' is incorrect in this example because the member
> > operator new hides the global operator new, so no operator new
> > can be found for T that does not require a second argument.
> 
> This seems inconsistent to me.  Other overloaded functions don't
> hide their neighbors, why should operator new()?  The standard way
> to hide a global is to declare a member with the same name and arguments.
> Then, if I (as class T author) want to disallow ::operator new(size_t),
> I can declare a private one and not define it.

No.  If the name is the same, the function is hidden.  For example:

	void foo(int);
	struct S {
		void foo();
		void bar();
	};
	void S::bar()
	{
		foo(1);   // error: unexpected  1 argument for S::foo()
	}


m
o
r
e

s
i
l
l
i
n
e
s
s
-- 
		Jonathan Shopiro
		AT&T Bell Laboratories, Warren, NJ  07060-0908
		research!shopiro   (201) 580-4229

kc@rna.UUCP (Kaare Christian) (05/12/91)

I haven't noticed any discussion of the following contradiction in the ARM:

In 5.3.3 there is a mention that operator new can be called with argument 0,
in which case it must return a pointer to an object.
In 12.5 it states that if operator new is called with argument 0, it must
return 0.

Also, the ARM defines a *nested* class as a class defined inside another
class, while a *local* class is a class defined inside a function. It then
defines a *local* type as a type defined inside a class. Shouldn't we
call 'em **nested** types?

Kaare Christian
kc@rna.rockefeller.edu

comeau@ditka.Chicago.COM (Greg Comeau) (05/16/91)

In article <1107@rna.UUCP> kc@rna.UUCP (Kaare Christian) writes:
>I haven't noticed any discussion of the following contradiction in the ARM:
>In 5.3.3 there is a mention that operator new can be called with argument 0,
>in which case it must return a pointer to an object.
>In 12.5 it states that if operator new is called with argument 0, it must
>return 0.


I had brought this issue up on BIX quite a while back.

12.5 is wrong.

>Also, the ARM defines a *nested* class as a class defined inside another
>class, while a *local* class is a class defined inside a function. It then
>defines a *local* type as a type defined inside a class. Shouldn't we
>call 'em **nested** types?

It should be local... as is.  The first line of 9.9 says it all to me:
"Type names obey exactly the same scope rules as other names."

"local" is a C++ scope.

- Greg
-- 
	 Comeau Computing, 91-34 120th Street, Richmond Hill, NY, 11418
                          Producers of Comeau C++ 2.1
          Here:attmail.com!csanta!comeau / BIX:comeau / CIS:72331,3421
                     Voice:718-945-0009 / Fax:718-441-2310