From dedd7df19cd01c14f5464a0c208434b084c6d8e9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=A1=D0=B5=D1=80=D0=B3=D0=B5=D0=B9=20=D0=9C=D0=B0=D1=80?= =?UTF-8?q?=D0=B8=D0=BD=D0=BA=D0=B5=D0=B2=D0=B8=D1=87?= Date: Tue, 5 Aug 2025 19:49:58 +0700 Subject: [PATCH] =?UTF-8?q?qosd:=20=D0=BE=D0=B1=D0=B5=D0=B7=D0=BE=D0=BF?= =?UTF-8?q?=D0=B0=D1=88=D0=B5=D0=BD=20=D0=BE=D0=B1=D1=85=D0=BE=D0=B4=20?= =?UTF-8?q?=D0=B4=D0=B5=D1=80=D0=B5=D0=B2=D0=B0=20=D1=81=20=D0=BC=D0=BE?= =?UTF-8?q?=D0=B4=D0=B8=D1=84=D0=B8=D0=BA=D0=B0=D1=86=D0=B8=D0=B5=D0=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Примеров итератора с доступом на чтение я много оставил, а пример модификации дерева только один. И тот я сразу забыл перевести на итераторы (range-based for loop). Т.к. проход теперь не по вектору (он давал экземпляр умного указателя), а по обычному указателю (собственному прокси, если точнее), то узел разрушался уже в процессе его отключения от дерева. Добавил удержание ссылки в сам `unlinkParent()` (ну, нам действительно может быть нужно только безвозвратное удаление поддерева) и пример в `main.cpp` расширил и прокомментировал. --- include/mixins/BaseLinkMixin.h | 10 +++++++++- src/main.cpp | 29 +++++++++++++++++++++++++---- 2 files changed, 34 insertions(+), 5 deletions(-) diff --git a/include/mixins/BaseLinkMixin.h b/include/mixins/BaseLinkMixin.h index 5501a71..bbe6965 100644 --- a/include/mixins/BaseLinkMixin.h +++ b/include/mixins/BaseLinkMixin.h @@ -37,7 +37,15 @@ public: auto parentLink = parent->getLink(); - parentLink->removeChild(getNode()); + /* NOTE: + * + * Keep a reference to the node we gonna to unlink. + * Otherwise, we'll disappear between `removeChild` and + * `setParent`. Do not rearrange these calls, because + * we want to modify the tree top down. + */ + auto node = getNode(); + parentLink->removeChild(node); getLink()->setParent(nullptr); } diff --git a/src/main.cpp b/src/main.cpp index 4e9ec49..2feb4e3 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -119,11 +119,32 @@ int main() { logger.info("Unlinking ComplexChild1 and ComplexChild3...\n"); child1->unlinkParent(); - for (auto child : root->getLink()->getChildren()) { - NodePtr childNode = std::dynamic_pointer_cast(child); - if (childNode->name() == "ComplexChild3") { - childNode->unlinkParent(); + for (auto child : traversal::BFS(root)) { + if (child->name() == "ComplexChild3") { + /* Avoid of disconnecting a node of the tree + * we're traversing. Method holds reference + * to it's object itself. But iterator ignores + * smart pointers, feeling free to dereference + * the destroyed object. + */ +#if 1 + /* Keep in mind to keep your reference until + * the cycle ends, if you want more than just + * remove subtree. + */ + NodePtr node = *child; + node->unlinkParent(); + std::cout << "Unlinked: " + << node->name() << std::endl; break; +#else + /* Otherwise, just break immediately you + * unlinked a node. The current pointer is not + * a valid pointer anymore. + */ + child->unlinkParent(); + break; +#endif } }