qosd: обезопашен обход дерева с модификацией
Примеров итератора с доступом на чтение я много оставил, а пример модификации дерева только один. И тот я сразу забыл перевести на итераторы (range-based for loop). Т.к. проход теперь не по вектору (он давал экземпляр умного указателя), а по обычному указателю (собственному прокси, если точнее), то узел разрушался уже в процессе его отключения от дерева. Добавил удержание ссылки в сам `unlinkParent()` (ну, нам действительно может быть нужно только безвозвратное удаление поддерева) и пример в `main.cpp` расширил и прокомментировал.
This commit is contained in:
@@ -37,7 +37,15 @@ public:
|
|||||||
|
|
||||||
auto parentLink = parent->getLink();
|
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);
|
getLink()->setParent(nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+25
-4
@@ -119,11 +119,32 @@ int main() {
|
|||||||
|
|
||||||
logger.info("Unlinking ComplexChild1 and ComplexChild3...\n");
|
logger.info("Unlinking ComplexChild1 and ComplexChild3...\n");
|
||||||
child1->unlinkParent();
|
child1->unlinkParent();
|
||||||
for (auto child : root->getLink()->getChildren()) {
|
for (auto child : traversal::BFS(root)) {
|
||||||
NodePtr childNode = std::dynamic_pointer_cast<INode>(child);
|
if (child->name() == "ComplexChild3") {
|
||||||
if (childNode->name() == "ComplexChild3") {
|
/* Avoid of disconnecting a node of the tree
|
||||||
childNode->unlinkParent();
|
* 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;
|
break;
|
||||||
|
#else
|
||||||
|
/* Otherwise, just break immediately you
|
||||||
|
* unlinked a node. The current pointer is not
|
||||||
|
* a valid pointer anymore.
|
||||||
|
*/
|
||||||
|
child->unlinkParent();
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user