Constructor calls
MyType* f = new MyType;
calls new to allocate a
MyType-sized piece of storage, then invokes the MyType constructor
on that storage, what happens if the storage allocation in new fails? The
constructor is not called in
that case, so although you still have an unsuccessfully created object, at least
you haven’t invoked the constructor and handed it a zero this
pointer. Here’s an example to prove it:
//: C13:NoMemory.cpp
// Constructor isn't called if new fails
#include <iostream>
#include <new> // bad_alloc definition
using namespace std;
class NoMemory {
public:
NoMemory() {
cout << "NoMemory::NoMemory()" << endl;
}
void* operator new(size_t sz) throw(bad_alloc){
cout << "NoMemory::operator new" << endl;
throw bad_alloc(); // "Out of memory"
}
};
int main() {
NoMemory* nm = 0;
try {
nm = new NoMemory;
} catch(bad_alloc) {
cerr << "Out of memory exception" << endl;
}
cout << "nm = " << nm << endl;
} ///:~
When the program runs, it does not print
the constructor message, only the message from operator new( ) and
the message in the exception handler. Because new never returns, the
constructor is never called so its message is not printed.
It’s important that nm be
initialized to zero because the new expression never completes, and the
pointer should be zero to make sure you don’t misuse it. However, you
should actually do more in the exception handler than just print out a message
and continue on as if the object had been successfully created. Ideally, you
will do something that will cause the program to recover from the problem, or at
the least exit after logging an error.
In earlier versions of C++ it was
standard practice to return zero from new if storage allocation failed.
That would prevent construction from occurring. However, if you try to return
zero from new with a Standard-conforming compiler, it should tell you
that you ought to throw bad_alloc
instead.