Розглянемо таку реалізацію списку, що стосується окремо:
struct node {
std::unique_ptr<node> next;
ComplicatedDestructorClass data;
}
Тепер, припустимо, я припиняю використовувати якийсь std::unique_ptr<node> head
екземпляр, який потім виходить за межі, викликаючи виклик його деструктора.
Чи вдасться це підірвати мій стек для достатньо великих списків? Чи справедливо припустити, що компілятор зробить досить складну оптимізацію (вбудований unique_ptr
деструктор в node
's, а потім використовувати хвостову рекурсію), що стає набагато складніше, якщо я виконую наступне (оскільки data
деструктор заблукає next
, робить це важким щоб компілятор помітив потенційну можливість упорядкування та виклику хвоста):
struct node {
std::shared_ptr<node> next;
ComplicatedDestructorClass data;
}
Якщо data
якимось чином є вказівник на його, node
то для рецидиву хвоста це може бути навіть неможливим (хоча, звичайно, ми повинні прагнути уникати таких порушень інкапсуляції).
Загалом, як тоді знищити цей список? Ми не можемо пройти через список та видалити "поточний" вузол, оскільки спільний вказівник не має release
! Єдиний спосіб - із користувацьким делетером, який мені справді смердючий.
gcc -O3
не вдалося оптимізувати хвостову рекурсію (на складному прикладі).