[comp.lang.c++] proposal for new/delete extension

djones@megatest.UUCP (Dave Jones) (06/26/91)

I would like to describe to you a small language-extension which I think
would prove useful. First I will describe the problem to be solved.

Occasionally, for the sake of efficiency, it is desirable to
allocate memory for new objects of a given class from a pool of preallocated
packets, sized by the sizeof() operator. It has been my experience that this
practice can improve the performance of some applications very significantly.
We therefore redefine the "new" and "delete" operators for the class.

class Class1 {
   		char goodies[SIZE];
	public:
		void *operator new(size_t);   // ignores the size_t
		void  operator delete(void *);
		// etc..
};

In general the new and delete declarations must be public, although classes
that are used only by a select number of friend-classes can declare the
the operators as private.

The problem here is that classes derived from Class1 will inherit
the new and delete operators. Because those operators manage a pool of
fixed-size packets, the inheritance is faulty.  It implies implicit casts
between void* and each of the base and derived classes, although only the
cast between void* and the base class is valid.

class Bogus: public Class1 {
		char more_goodies[SIZE2];
	public:
		// etc.
};

The above class Bogus will probably be allocated only "SIZE" bytes of memory
by the (inherited) operator new. Its actual size is likely to be
SIZE + SIZE2.

I recommend an alternate way to specify class-specific operators new
and delete which stipulates that they must not be inherited:

class Class1 {
		char goodies[SIZE];
	public:
		Class1 *operator new();
		void    operator delete(Class1*);
};

Notice that this version of operator new does not take a size_t parameter.
Notice also that both the declarations for both operators specify that they
manage memory specifically for Class1, not for (void*) classes of arbitrary
size and alignment. Operators declared this way would override the default or
inherited operators new and delete in Class1 only, not in derived classes.
Stated another way, there would be no implicit casts of void* implied
by these operators.

alanb@sdl.mdcbbs.com (06/26/91)

In article <19215@prometheus.megatest.UUCP>, djones@megatest.UUCP (Dave Jones) writes:
> 
> 
> I would like to describe to you a small language-extension which I think
> would prove useful. First I will describe the problem to be solved.
> 
> Occasionally, for the sake of efficiency, it is desirable to
> allocate memory for new objects of a given class from a pool of preallocated
> packets, sized by the sizeof() operator. It has been my experience that this
> practice can improve the performance of some applications very significantly.
> We therefore redefine the "new" and "delete" operators for the class.
> 
> class Class1 {
>    		char goodies[SIZE];
> 	public:
> 		void *operator new(size_t);   // ignores the size_t
> 		void  operator delete(void *);
> 		// etc..
> };
> 
[Detail omitted]
> 		Class1 *operator new();
> 		void    operator delete(Class1*);

Sounds plausible. As a workround, would the following work?
void *Class1::operator new(size_t s)
{
    // If default new doesn't work, Class2 needs to redefine operator new anyway
    if (s != sizeof(Class1))
	return ::operator new(s);  

    // Do fixed pool stuff here
}

horstman@mathcs.sjsu.edu (Cay Horstmann) (06/27/91)

In article <19215@prometheus.megatest.UUCP> djones@megatest.UUCP (Dave Jones) writes:
>
>I recommend an alternate way to specify class-specific operators new
>and delete which stipulates that they must not be inherited:
>
>class Class1 {
>		char goodies[SIZE];
>	public:
>		Class1 *operator new();
>		void    operator delete(Class1*);
>};
>
>Notice that this version of operator new does not take a size_t parameter.

Let me split this up into two points.
(1) I think that defining operator new() instead of operator new(size_t) as
    a fixed-size allocator that cannot be inherited is a reasonable idea. 
    (PLEASE don't ask to inherit it in only those classes that don't add 
    any data.)
(2) I think the question whether that operator new, or any operator new,
    should return a Class* rather than a void*, is an independent question.
    Even in the normal case, with inherited operator new, it makes sense
    to return a Class*. Why DOES operator new return a void* in C++?
	 The standard argument is that the constructor has to first run on the
    allocated block of memory to turn the bits into an object.

If you want to push your idea of a size-specific, non-inheritable operator
new, I think you should just stick to void* Class::operator new(). 

Cay