- Failure to Distinguish Scalar and Array Allocation
- Checking for Allocation Failure
- Replacing Global New and Delete
- Confusing Scope and Activation of Member new and delete
- Throwing String Literals
- Improper Exception Mechanics
- Abusing Local Addresses
- Failure to Employ Resource Acquisition Is Initialization
- Improper Use of auto_ptr
Gotcha #63: Confusing Scope and Activation of Member new and delete
Member operator new and operator delete are invoked when objects of the class declaring them are created and destroyed. The actual scope in which the allocation expression occurs is immaterial:
class String { public: void *operator new( size_t ); // member operator new void operator delete( void * ); // member operator delete void *operator new[]( size_t ); // member operator new[] void operator delete [] ( void * ); // member operator delete[] String( const char * = "" ); // . . . }; void f() { String *sp = new String( "Heap" ); // uses String::operator new int *ip = new int( 12 ); // uses ::operator new delete ip; // uses :: operator delete delete sp; // uses String::delete }
Again: the scope of the allocation doesn't matter; it's the type being allocated that determines the function called:
String::String( const char *s ) : s_( strcpy( new char[strlen(s)+1], s ) ) {}
The array of characters is allocated in the scope of class String, but the allocation uses the global array new, not String's array new; a char is not a String. Explicit qualification can help:
String::String( const char *s ) : s_( strcpy( reinterpret_cast<char *> (String::operator new[](strlen(s)+1 )),s ) ) {}
It would be nice if we could say something like String::new char[strlen(s)+1] to access String's operator new[] through the new operator (parse that!), but that's illegal syntax. (Although we can use ::new to access a global operator new and operator new[] and ::delete to access a global operator delete or operator delete[].)