Considera la seguente implementazione dell'elenco collegato singolarmente:
struct node {
std::unique_ptr<node> next;
ComplicatedDestructorClass data;
}
Ora supponiamo che smetta di usare qualche std::unique_ptr<node> head
istanza che poi esca dall'ambito, facendo chiamare il suo distruttore.
Questo farà esplodere il mio stack per liste sufficientemente grandi? È lecito ritenere che il compilatore eseguirà un'ottimizzazione piuttosto complicata (inline unique_ptr
's destructor in node
's, quindi usa la ricorsione della coda), che diventa molto più difficile se faccio quanto segue (dal momento che il data
distruttore potrebbe offuscare quello next
, rendendolo difficile per il compilatore notare il potenziale riordino e opportunità di coda):
struct node {
std::shared_ptr<node> next;
ComplicatedDestructorClass data;
}
Se in data
qualche modo ha un puntatore al suo, node
allora potrebbe anche essere impossibile per la ricorsione della coda (anche se ovviamente dovremmo cercare di evitare tali violazioni dell'incapsulamento).
In generale, come si può distruggere questa lista altrimenti, allora? Non possiamo attraversare l'elenco ed eliminare il nodo "corrente" perché il puntatore condiviso non ha un release
! L'unico modo è con un deleter personalizzato, che è davvero maleodorante per me.
gcc -O3
non è stato in grado di ottimizzare una ricorsione della coda (in un esempio complicato).