April 18, 2008, 11:13 p.m.
posted by nogood
Item 34. Restricting Heap AllocationSometimes it's a good idea to indicate that objects of a particular class should not be allocated on the heap. Often this is to ensure that the object's destructor is called, as in the case of a "handle" object that maintains a reference count for a "body" object. Local objects with automatic storage class will have their destructors called automatically (except in the case of abnormal program termination via an exit or abort), as will objects with static storage class (except in the case of an abort), whereas heap-allocated objects must be destroyed explicitly. One way to indicate such a preference is by defining heap memory allocation to be illegal:
class NoHeap {
public:
//...
protected:
void *operator new( size_t ) { return 0; }
void operator delete( void * ) {}
};
Any conventional attempt to allocate a NoHeap object on the heap will result in a compile-time error (see Class-Specific Memory Mangement [36, 123]): NoHeap *nh = new NoHeap; // error! protected NoHeap::operator new //... delete nh; // error! protected NoHeap::operator delete The operator new and operator delete members are defined (as well as declared) because they may be called implicitly from constructors and destructors on some platforms. They are declared to be protected for the same reason; they may be invoked implicitly from derived class constructors and destructors. If NoHeap is not intended for use as a base class, these functions may be declared to be private. At the same time, we may also want to pay attention to allocation of arrays of NoHeap objects (see Array Allocation [37, 127]). In this case, we can simply declare array new and array delete to be private and undefined, similar to the way we deny copy operations (see Preventing Copying [32, 111]).
class NoHeap {
public:
//...
protected:
void *operator new( size_t ) { return 0; }
void operator delete( void * ) {}
private:
void *operator new[]( size_t );
void operator delete[]( void * );
};
It's also possible to encourage, rather than discourage, heap allocation. Just make the destructor private:
class OnHeap {
~OnHeap();
public:
void destroy()
{ delete this; }
//...
};
Any ordinary attempt to declare an automatic or static OnHeap object will result in an implicit destructor call when the object's name goes out of scope. OnHeap oh1; // error! implicit call of private dtor void aFunc() { OnHeap oh2; //... // error! implicit dtor call for oh2 } |
- Comment