La cosa migliore è catturare l'eccezione nel costruttore e settare un flag.
codice:
class A {
public:
A() : p(0), k(0) {
p = new int; // questo funge
k = new int; // questo solleva una bad_alloc
}
~A() {
delete p;
delete k;
}
private:
int* p;
int* k;
};
se l'eccezione non viene catturata nel costruttore, nessuno libera la memoria di p. In più l'esecuzione si arresta al momento dell'eccezione e l'oggetto rimane incompleto e il distruttore non è invocato.
Un modo un pò laborioso è il seguente.
codice:
class A {
public:
A() : p(0), k(0),init_ok(false) {
try {
p = new int; // questo funge
} catch (std::bad_alloc& err) {
p=0;
init_ok = false;
}
try {
k = new int; // questo solleva una bad_alloc
} catch (std::bad_alloc& err) {
k=0;
init_ok = false;
}
init_ok = true;
}
~A() {
delete p;
delete k;
}
bool ok() const { return init_ok;}
private:
int* p;
int* k;
bool init_ok;
};
In questo caso l'eccezione è catturata e si setta il flag per poi controllarlo in un punto esterno del codice. (Ed eventualmente lanciare una successiva eccezione).
Questo garantisce che il distruttore venga richiamato sempre.