Vita di un oggetto lanciato catturato da riferimento
-
22-09-2019 - |
Domanda
Il C ++ standard, paragrafo 15.1.4 sais:
La memoria per la copia temporanea del all'eccezione generata viene allocata in modo specificato, eccetto come indicato in 3.7.3.1. Il temporanea persiste fino a quando v'è un gestore in corso di esecuzione per tale eccezione.
Mi chiedo il motivo per cui questo codice si blocca (so che non è delle migliori pratiche):
class magicException
{
private:
char* m_message;
public:
magicException(const char* message)
{
m_message = new char[strlen(message) + 1];
strcpy(m_message, message);
}
~magicException()
{
cout << "Destructor called." << endl;
delete[] m_message;
}
char* getMessage()
{
return m_message;
}
};
void someFunction()
{
throw magicException("Bang!");
}
int main(int argc, char * argv[])
{
try
{
someFunction();
}
catch (magicException& ex)
{
cout << ex.getMessage() << endl;
}
return 0;
}
In particolare, il distruttore dell'oggetto magicException gettato viene chiamato prima del blocco catch. Se io invece aggiungo un costruttore di copia per la mia classe:
magicException(const magicException& other)
{
cout << "Copy constructor called." << endl;
m_message = new char[strlen(other.m_message) + 1];
strcpy(m_message, other.m_message);
}
Poi il codice funziona, il distruttore viene chiamato nel luogo previsto (fine del blocco catch), ma è interessante notare il costruttore di copia ancora non viene chiamato. E 'ottimizzato via dal compilatore (Visual C ++ 2008 con ottimizzazioni spento), o mi sto perdendo qualcosa?
Soluzione
In particolare, il distruttore della oggetto magicException gettato ottiene chiamato prima del blocco catch.
Sì, come il tuo preventivo dallo standard dice, una copia è preso dal compilatore, e l'originale (probabilmente) scartata. Il tuo problema è la mancanza di un costruttore di copia nel codice originale. Tuttavia, un compilatore C ++ è permesso di rimuovere (o aggiungere) copiare le chiamate costruttore in tutti i tipi di situazioni, compreso questo.