If all data types are made non-recursive using tricks like a table of node IDs linking to data and data uses only other node IDs to form a graph, then can all memory be managed using just Reference Counting?
Lo spostamento da puntatori come riferimenti a riferimenti basati su ID non modifica il problema. In effetti può peggiorare la situazione!
Le proprietà dei dati immutabili sono piuttosto forti e anche con tipi di dati ricorsivi , i dati immutabili sopprimono i cicli di riferimento del puntatore, poiché un oggetto / dati vecchio non poteva conoscere un riferimento oggetto creato in futuro quando è stato creato (quindi non può fare riferimento a oggetti futuri) e inoltre non può più essere modificato per fare riferimento a un nuovo oggetto. Pertanto, i dati immutabili sono sempre diretti e aciclici in relazione ai riferimenti basati su puntatori.
Tuttavia, usando ID o nomi come meccanismo di riferimento, può essere creato un oggetto immutabile che fa riferimento a un oggetto immutabile futuro, che fa riferimento al vecchio oggetto immutabile, e quindi, usando nomi per riferimenti invece di puntatori, possiamo creare cicli con immutabile i dati.
Furthermore is it possible to express a immutable list with the standard set of Haskell-like functions for the list in a language like C++ and guarantee no memory leaks using only reference counting?
Un elenco collegato singolarmente, sì. Tuttavia, per una lista doppiamente collegata: una lista doppiamente collegata è un tipo di dati ricorsivo che crea anche cicli con riferimenti basati su puntatori.
Il conteggio dei riferimenti semplice o ingenuo non riuscirebbe a rilasciare alcun nodo della lista, se l'elenco nel suo complesso non fosse referenziato. L'unico modo per raccogliere gli elementi sarebbe eliminarli tutti dalla lista.
Il conteggio dei riferimenti intelligenti sarebbe necessario per gestirli, il che significa che i vari riferimenti devono essere differenziati, come @amon descrive, ad esempio, come strong o debole. I forti contano e quelli deboli no. Alcuni sistemi tentano una differenziazione strong vs debole a runtime, dinamicamente e automaticamente; altri sistemi etichettano i riferimenti in fase di compilazione tramite il sistema di tipi; alcuni mescolano i due.
Dai un'occhiata a Objective C e Swift, usano Conteggio dei riferimenti automatici (automatico come assistenza fornita dal compilatore) per la loro gestione della memoria. Nota anche le aree problematiche per ARC, in particolare intorno alle chiusure .
E tuttavia ancora, nei linguaggi raccolti con garbage collection, come Java e C #, abbiamo facilmente e comunemente "perso" memoria. Tutto ciò di cui hai bisogno è una collezione di dati o una struttura di dati di lunga durata che cresce nel tempo ma non viene adeguatamente ridotta nel tempo. Questa è una nozione leggermente diversa di perdita di memoria, ma ha lo stesso effetto in quanto se il programma viene eseguito abbastanza a lungo, esaurirà la memoria. Questo può accadere anche in linguaggi funzionali che applicano dati immutabili, come ad esempio Erlang .