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> headistanza 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 datadistruttore 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 dataqualche modo ha un puntatore al suo, nodeallora 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 -O3non è stato in grado di ottimizzare una ricorsione della coda (in un esempio complicato).