2009-12-07 11 views
5

Si consideri il seguente codice:cattura oggetti eccezione per riferimento, provvisori, i problemi di durata

#include <iostream> 
#include <stdexcept> 

void foo() 
{ 
    throw std::runtime_error("How long do I live?"); 
} 

int main() 
{ 
    try 
    { 
     foo(); 
    } 
    catch (std::runtime_error& e) 
    { 
     std::cout << e.what() << std::endl; 
    } 
} 

Perché posso intercettare l'eccezione per riferimento, non è un std::runtime_error("How long do I live?") rvalue?

Come mai l'oggetto eccezione è ancora attivo nel blocco catch?

Dove vengono memorizzati gli oggetti eccezionalmente memorizzati? Qual è la loro vita?

risposta

5

Un'eccezione generata non è temporanea: il codice di eccezione generato dal compilatore ne mantiene una copia permanente. Quindi puoi associarlo a un riferimento non const.

[modifica] Ho appena controllato lo standard e in realtà si riferisce a una copia temporanea. Tuttavia, la durata del temporaneo è garantita almeno per il tempo del gestore di eccezioni.

7

Nello standard C++, paragrafo 15.1.4:

La memoria per la copia temporanea l'eccezione che sono gettati è allocata in modo non specificato, salvo quanto riportato in 3.7.3.1. Il temporaneo persiste fintanto che esiste un gestore in esecuzione per l'eccezione . In particolare, se un gestore termina eseguendo un lancio; , che passa il controllo a un altro gestore per la stessa eccezione , quindi il temporaneo rimane. Quando l'ultimo gestore in esecuzione per l'eccezione esce con qualsiasi mezzo diverso da quello di lancio; l'oggetto temporaneo viene distrutto e l'implementazione può deallocare la memoria per l'oggetto temporaneo ; tale deallocazione viene eseguita in modo non specificato . La distruzione si verifica immediatamente dopo la distruzione di dell'oggetto dichiarato nella dichiarazione di eccezione nel gestore.

Si noti che, in linguaggio C++ standard, un gestore denota un blocco catch con il tipo di argomento corretto.

+0

Il testo in grassetto non si riferisce all'oggetto temporaneo creato nell'espressione di lancio. Il fatto importante è che il meccanismo di lancio delle eccezioni ne fa una copia temporanea in alcune aree private, e quindi mantiene la copia in vita. La copia privata è ciò che ricevono gli handler. – bames53

2

Come diceva Neil, è in corso la magia del compilatore interno. Inoltre, tenere presente che il compilatore può creare any number of copies dell'oggetto eccezione.

1

Complimenti per aver cercato di comprendere i dettagli della lingua. Allo stesso tempo, IMHO, è molto più importante capire perché tu dovresti catturare un'eccezione per riferimento (e lanciarla per valore), del perché tu puoi.

Le persone utilizzano in genere una gerarchia di classi di eccezioni e l'acquisizione per riferimento consente di sfruttare il polimorfismo e rilevare un'eccezione della classe base, quando non è necessario gestire separatamente i singoli tipi di eccezione. Se non si riuscisse a prendere come riferimento, si sarebbe dovuto scrivere una clausola catch per ogni possibile tipo di eccezione che può essere generata nella clausola try.

Problemi correlati