Pagina 1 di 2 1 2 ultimoultimo
Visualizzazione dei risultati da 1 a 10 su 15
  1. #1

    [C++] smart pointer vs garbage collector

    Spero che la domanda non sia troppo generica e fuori argomento per questo forum, da quando ho iniziato a studiare il C++ mi capita spesso di leggere lamentele sul fatto che questo non include un garbage collector.
    Vi chiedo quali vantaggi e svantaggi ha l'uno rispetto all'altro, e perché un programmatore dovrebbe utilizzare un garbage collector al posto di shared_ptr. Grazie mille

  2. #2
    Utente di HTML.it
    Registrato dal
    Dec 2004
    Messaggi
    286
    Principalmente il C++ non contiene un GC a livello nativo perché è un linguaggio ancora destinato ad un codice ottimizzato. In altre parole, il C++ dovrebbe mettere in condizioni il programmatore di scegliere la pratica di programmazione che gli risulta più confacente a seconda dei risultati che vuole ottenere, tra questi anche la possibilità di scrivere codice ottimizzato nelle prestazioni e software di sistema in generale. Ricordo che con un compilatore C++ è ancora possibile compilare codice C. L'implementazione di un GC a livello nativo costringerebbe in ogni caso il compilatore ad un overheading sul codice generato, limitando le prestazioni e lescelte del programmatore. Personalmente penso che chi si lamenta della mancanza di un GC integrato nel C++, forse non ha bisogno del C++ ma potrebbe benissimo programmare con altri linguaggi spesso anche più semplici.

  3. #3
    Anche l'uso dei migliori smart pointers attualmente impiegati non risolve in maniera automatica gli eventuali reference cycles, e comunque anche gli shared_ptr hanno un costo a runtime (devono essere sincronizzati, mantenere un reference count, e così via). Il GC solleva il programmatore dal doversi ricordare di usare delete (che sarebbe esplicito nel caso di puntatori "normali", implicito con gli smart pointers).
    Tuttavia, anche usando un GC la gestione delle risorse va fatta "alla vecchia maniera", dato che la cancellazione degli oggetti attuata dal GC non è deterministica, e può accadere in qualunque momento (il quale "qualunque momento", se si consuma poca memoria, può essere benissimo il termine del programma), il che non si concilia con oggetti che tengono aperte risorse condivise (file, socket, mutex, ...). Non è un caso che anche nei linguaggi dotati di GC esistano costrutti per gestire in altra maniera la liberazione delle risorse incapsulate (vedi il costrutto using e l'interfaccia IDisposable del C#).

    Lo stato attuale delle cose in C++ ha un vantaggio rispetto al GC: la gestione della memoria e delle risorse è attuata alla stessa maniera, ossia tramite la RAII, che funziona grazie al fatto che gli oggetti allocati sullo stack vengono distrutti automaticamente in ogni caso quando vanno fuori scope. Inoltre il solo fatto che in C++ si usi molto lo stack anche per gli oggetti (mentre nei linguaggi con GC si usa quasi solo l'heap) fa sì che la necessità di un GC sia molto meno sentita.
    Amaro C++, il gusto pieno dell'undefined behavior.

  4. #4
    Utente di HTML.it L'avatar di shodan
    Registrato dal
    Jun 2001
    Messaggi
    2,381
    Personalmente, sentire di GC in C++ mi fa venire l'orticaria.
    Al di la del mio parere personale qui c'è un articolo che mette a confronto C++, Java, C# e D sull'argomento:
    http://www.eptacom.net/pubblicazioni/pub_it/iso_12.html
    This code and information is provided "as is" without warranty of any kind, either expressed
    or implied, including but not limited to the implied warranties of merchantability and/or
    fitness for a particular purpose.

  5. #5
    grazie a tutti per le risposte e grazie shodan per il link, davvero interessante. ho capito che il gc per una serie di motivi non è l'ideale nel c++, ad es. perché per via del suo "indeterminismo" il distruttore perde gran parte della sua utilità.
    mi chiedo, cosa pensate voi del costrutto "finally"? perché non è presente nel c++? bjarne dice che non è stato implementato perché gli smart pointers lo sostituiscono e svolgono il lavoro in modo migliore. voi siete d'accordo? perché non implementarlo e lasciare al programmatore la scelta?
    esiste un modo pulito di "mimare" il finally?
    ad esempio avendo un programma che utilizza al 90% classi derivate dalla stessa classe base, ha senso utilizzare un riferimento a questa classe base come parametro dell'eccezione, e poi questa al suo interno richiama il distruttore della classe derivata (dell'oggetto) che ha generato l'eccezione? ha senso?
    pensate che l'uso di shared_ptr + weak_ptr risolva tutti i problemi, compreso quello dei "reference cycles"?

    EDIT:

    oppure si può far implementare a tutte le classi una stessa interfaccia che si occupa della gestione delle eccezioni, e poi tramite questa fare sì che venga chiamato automaticamente il distruttore dell'oggetto che ha generato l'eccezione? è una cosa fattibile o sto sparando cretinate?

  6. #6
    Originariamente inviato da serenasere24
    grazie a tutti per le risposte e grazie shodan per il link, davvero interessante. ho capito che il gc per una serie di motivi non è l'ideale nel c++, ad es. perché per via del suo "indeterminismo" il distruttore perde gran parte della sua utilità.
    Nota che l'indeterminismo del distruttore in realtà non è un problema insormontabile (nei linguaggi con GC ci si convive), ma in C++ la cosa secondo me sarebbe particolarmente incasinata perché il determinismo/indeterminismo del distruttore dipenderebbe da come è stato allocato l'oggetto, dato che se viene allocato sullo stack viene distrutto subito, se nell'heap bisogna aspettare il GC.
    mi chiedo, cosa pensate voi del costrutto "finally"? perché non è presente nel c++? bjarne dice che non è stato implementato perché gli smart pointers lo sostituiscono e svolgono il lavoro in modo migliore. voi siete d'accordo? perché non implementarlo e lasciare al programmatore la scelta?
    Più che degli smart pointers si parla di RAII (dato che è un concetto che si applica non solo alla memoria, ma anche e soprattutto alle altre risorse). Credo che sia stata una decisione fatta per "forzare" il programmatore ad encapsulare le risorse in classi che ne detengono la proprietà, il che in effetti consente di creare codice robusto ed elegante. Va detto però che in alcuni casi finally può essere necessario.
    esiste un modo pulito di "mimare" il finally?
    http://www.boost.org/doc/libs/1_45_0...tml/index.html
    ad esempio avendo un programma che utilizza al 90% classi derivate dalla stessa classe base, ha senso utilizzare un riferimento a questa classe base come parametro dell'eccezione, e poi questa al suo interno richiama il distruttore della classe derivata (dell'oggetto) che ha generato l'eccezione? ha senso?
    Non mi è ben chiaro di cosa tu stia parlando...
    pensate che l'uso di shared_ptr + weak_ptr risolva tutti i problemi, compreso quello dei "reference cycles"?
    Teoricamente sì, anche se personalmente preferisco evitare l'ownership condivisa (per quanto talvolta sia necessaria), una semantica di ownership stretta secondo me è preferibile ove possibile, dato che diventa veramente difficile fare errori.
    Amaro C++, il gusto pieno dell'undefined behavior.

  7. #7
    MItaly, perdonami se approfitto della tua disponibilità:

    Credo che sia stata una decisione fatta per "forzare" il programmatore ad encapsulare le risorse in classi che ne detengono la proprietà, il che in effetti consente di creare codice robusto ed elegante.
    non ho capito bene il senso di "encapsulare le risorse in classi che ne detengono la proprietà".

    In altre parole sarebbe un po' la differenza che c'è tra un puntatore raw ed uno smart_pointer, che in effetti è una classe che contiene un puntatore raw come membro.
    Quindi nel secondo caso il puntatore raw è incapsulato all'interno della classe smartPtr (ad esempio) che ne detiene la priorità? E l'uso di finally permetterebbe ai programmatori di ignorare l'incapsulamento ed utilizzare direttamente un puntatore comune "tanto poi c'è finally, chi se ne frega di incapsulare"?

    Non mi è ben chiaro di cosa tu stia parlando...
    ahah come immaginavo, non so neanch'io cosa ho detto!
    Fai finta che io non abbia detto niente!

    Grazie per il link, mi devo decidere a scaricare questa libreria!

  8. #8
    Originariamente inviato da serenasere24
    MItaly, perdonami se approfitto della tua disponibilità:
    Nessun problema, figurati.
    non ho capito bene il senso di "encapsulare le risorse in classi che ne detengono la proprietà".

    In altre parole sarebbe un po' la differenza che c'è tra un puntatore raw ed uno smart_pointer, che in effetti è una classe che contiene un puntatore raw come membro.
    Quindi nel secondo caso il puntatore raw è incapsulato all'interno della classe smartPtr (ad esempio) che ne detiene la priorità? E l'uso di finally permetterebbe ai programmatori di ignorare l'incapsulamento ed utilizzare direttamente un puntatore comune "tanto poi c'è finally, chi se ne frega di incapsulare"?
    Esatto, il concetto è questo.
    ahah come immaginavo, non so neanch'io cosa ho detto!
    Fai finta che io non abbia detto niente!
    Come preferisci; comunque se ti viene in mente cosa volevi dire chiedi pure.
    Grazie per il link, mi devo decidere a scaricare questa libreria!
    Guarda, boost è davvero fenomenale, sia perché ti fornisce un sacco di roba di qualità già pronta, sia perché è una fonte d'ispirazione notevole in termini di design del codice (usando boost si capisce lo stile C++ "moderno").
    Amaro C++, il gusto pieno dell'undefined behavior.

  9. #9
    Come preferisci; comunque se ti viene in mente cosa volevi dire chiedi pure.
    ahaha ti ringrazio, ma in effetti mi hai fatto capire che nel mio caso basterebbe un semplice auto_ptr, e non ha senso fasciarmi la testa prima di rompermela. Poi magari se mi troverò in difficoltà con auto_ptr proverò altre strade, ma per ora si tratta solo di viaggi mentali e di fare il passo più lungo della gamba (maledetta curiosità).

    codice:
    Guarda, boost è davvero fenomenale, sia perché ti fornisce un sacco di roba di qualità già pronta, sia perché è una fonte d'ispirazione notevole in termini di design del codice (usando boost si capisce lo stile C++ "moderno").
    Il fatto è che ancora non conosco bene la libreria standard, forse è meglio se mi esercito bene su quella, con i vettori, i contenitori ecc.. e poi provo boost, altrimenti rischio di mettere troppa carne sul fuoco, anche se ora mi hai aumentato la voglia di provarla XD
    ti ringrazio tanto per le tue spiegazioni chiare e utili come al solito!

  10. #10
    Amaro C++, il gusto pieno dell'undefined behavior.

Permessi di invio

  • Non puoi inserire discussioni
  • Non puoi inserire repliche
  • Non puoi inserire allegati
  • Non puoi modificare i tuoi messaggi
  •  
Powered by vBulletin® Version 4.2.1
Copyright © 2024 vBulletin Solutions, Inc. All rights reserved.