Quando utilizzare effettivamente RAII?

2

Capisco il concetto di RAII: Utilizzare il distruttore come mezzo per liberare risorse, come la memoria, o chiudere handle di file / connessioni database. Provenendo da uno sfondo Java, questo in realtà era piuttosto facile da capire a causa delle somiglianze con finally .

Tuttavia, non capisco quando effettivamente dovresti applicarlo. Ovviamente dovrebbe essere implementato durante l'inizializzazione degli oggetti nell'heap, ma quali sono gli altri scenari per i quali un normale programmatore dovrebbe usarlo? Esaminando questo thread ho trovato fuori che per esempio std::ifstream ha già implementato RAII per gestire la liberazione del suo handle di file. Quindi avvolgerlo in un altro oggetto solo per chiamare ifstreamObj.close() nel suo distruttore sarebbe una perdita di tempo. Ma sono abbastanza sicuro che questa non è una regola generale che si applica a tutte le librerie là fuori.

Quindi la mia domanda è: quando dovrei effettivamente usare RAII? Esiste una regola empirica generale, una best practice o devo strisciare attraverso la documentazione di ogni classe se voglio essere sicuro? Oppure posso essere certo che ogni classe che implementa un metodo close() / free() / delete() (o qualcosa di simile) si occupa anche di chiamarla correttamente quando necessario?

    
posta KUSH42 21.04.2017 - 23:03
fonte

2 risposte

6

when should I actually use RAII?

Quando acquisisci una risorsa nelle funzioni membro della tua classe e non hai delegato la responsabilità di rilasciare tali risorse a un altro oggetto / funzione, devi assicurarti di rilasciare tali risorse nel distruttore.

Se la tua classe acquisisce un handle di file utilizzando std::ifstream::open() , non dovresti chiamare esplicitamente std::ifstream::close() poiché il distruttore di std::ifstream si prenderà cura di esso, cioè la responsabilità è stata delegata a un altro oggetto.

Tuttavia, se la tua classe acquisisce un handle di file utilizzando fopen() , dovrai assicurarti che il distruttore della tua classe chiami fclose() in modo appropriato.

Is there a general rule of thumb, a best-practice, or do I have to crawl through each and every class's documentation if I want to be sure?

Come regola del thump, dovresti assumere che ogni classe che usi, sia che si tratti della libreria standard, della libreria di un venditore o della libreria interna, aderisce al principio. In caso contrario, è un difetto e deve essere risolto dalla parte responsabile.

Non dovresti chiamare std::ifstream::close() . Se il file non viene chiuso, è necessario informare il fornitore che è necessario risolvere il problema. Nel frattempo, dovresti scrivere una classe wrapper che si prenda cura del problema e utilizzare la classe wrapper in resto del tuo codice.

    
risposta data 21.04.2017 - 23:21
fonte
2

RAII riguarda il rilascio automatico delle risorse acquisite nel distruttore - esiste una garanzia di run-time che il distruttore verrà chiamato prima che l'istanza dell'oggetto stia andando via indipendentemente dal meccanismo specifico usato.

Quindi dovrebbe essere usato sempre. Allo stesso tempo, quando l'oggetto sta andando via, anche i suoi membri stanno andando via e ognuno avrà il suo distruttore eseguito sulla via d'uscita. Quindi se questi oggetti membri sono implementati correttamente non è necessario fare nulla.

Un idioma molto popolare è quello di creare un oggetto titolare nello stack in modo che le risorse vengano liberate quando si esce dall'ambito (inclusa l'eccezione generata)

    
risposta data 22.04.2017 - 00:42
fonte

Leggi altre domande sui tag