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