Рассмотрим следующую реализацию односвязного списка:
struct node {
std::unique_ptr<node> next;
ComplicatedDestructorClass data;
}
Теперь предположим, что я перестал использовать некоторый std::unique_ptr<node> headэкземпляр, который затем выходит из области видимости, вызывая вызов его деструктора.
Будет ли это удар по моему стеку для достаточно больших списков? Справедливо ли предположить, что компилятор будет выполнять довольно сложную оптимизацию (встроенный unique_ptrдеструктор в node, а затем использовать хвостовую рекурсию), что будет намного сложнее, если я сделаю следующее (поскольку dataдеструктор будет запутывать next, делая его трудным чтобы компилятор заметил потенциальную возможность переупорядочения и возможности хвостового вызова):
struct node {
std::shared_ptr<node> next;
ComplicatedDestructorClass data;
}
Если dataкаким-то образом есть указатель на его, nodeтогда это может быть даже невозможно для хвостовой рекурсии (хотя, конечно, мы должны стремиться избегать таких нарушений инкапсуляции).
В общем, как можно иначе уничтожить этот список? Мы не можем просмотреть список и удалить «текущий» узел, потому что у общего указателя нет release! Единственный способ - с помощью пользовательского удалителя, который действительно воняет для меня.
gcc -O3не удалось оптимизировать хвостовую рекурсию (в сложном примере).