cattura l’eccezione con il puntatore in C ++

Ho scoperto che ci sono tre modi per catturare un’eccezione, quali sono le differenze?

1) cattura per valore;

2) cattura per riferimento;

3) cattura con il puntatore;

So solo che catch by value invocherà due copie dell’object, catch by reference ne invocherà una. Allora, che ne dici di prendere il puntatore? Quando usare catch by pointer? Oltre a lanciare un object, posso lanciare un puntatore su un object come questo?

class A {} void f() { A *p = new A(); throw p; } 

Il modo consigliato è quello di tirare per valore e catturare per riferimento .

Il tuo codice di esempio genera un puntatore, che è una ctriggers idea dal momento che dovresti gestire la memoria nel sito di cattura.

Se ritieni davvero di dover lanciare un puntatore, usa un puntatore intelligente come shared_ptr .

Comunque, Herb Sutter e Alexei Alexandrescu lo spiegano molto bene nel loro libro sugli standard di codifica C ++ che ho parafrasato.

Vedi gli standard di codifica C ++: Throw by Value, Catch by Reference .

Catch segue le normali regole di compatibilità di assegnazione, ovvero, se si lancia un valore, è ansible prenderlo come valore o riferimento, ma non come puntatore; se si lancia un puntatore, è ansible catturarlo solo come puntatore (o riferimento a un puntatore …).

Ma non ha senso lanciare i puntatori, causerà solo mal di testa nella gestione della memoria. Pertanto, dovresti, in generale, seguire la regola del tiro per valore, prendere per riferimento , come spiegato da Gregory.

MFC di Microsoft utilizza catch by pointer, ma penso che fosse compatibile con il compilatore prima che try e catch fossero implementati correttamente; in origine utilizzavano le macro TRY e CATCH per simularlo. Ogni eccezione deriva da CException, che ha un metodo per determinare se l’object deve essere cancellato.

Non lo consiglierei per qualsiasi progetto di eccezione moderno. Prendere per riferimento è la strada da percorrere.

Mentre è ansible lanciare praticamente qualsiasi object di qualsiasi tipo, c’è poco (se non altro) da guadagnare facendo questo. L’allocazione dynamic è utile soprattutto quando un object deve avere una durata che non si adatta all’allocazione automatica, ovvero si desidera che la sua durata sia indipendente dal normale ambito del programma.

Nel caso di un object di eccezione, tuttavia, ciò non ha molto senso. Un object eccezione viene normalmente utilizzato solo all’interno di un gestore di eccezioni e si desidera chiaramente che venga distrutto quando si esce dal gestore (ultimo) per tale eccezione.

C’è anche il fatto che in genere si desidera mantenere il codice di gestione delle eccezioni in modo abbastanza semplice. Ad esempio, se stai cercando di segnalare che lo store / heap libero è esaurito o corrotto, provare ad allocare il tuo object di eccezione su quello store / heap esausti / corrotti di solito non funzionerà molto bene …

Non c’è davvero un buon scenario per catturare / lanciare un’eccezione tramite puntatore. La semantica C ++ lo consente, ma non è terribilmente utile, poiché la maggior parte delle volte si lancia un’eccezione temporanea o un object stringa.

Tuttavia, alcune librerie (Boost.Graph fa questo, credo) usano throw per passare un valore di ritorno al chiamante da una funzione profondamente ricorsiva; in una situazione come questa, il valore restituito può essere un puntatore, quindi lanciare un puntatore avrebbe senso.