C++ c++;在通知父级的同时删除树结构中的所有子级
考虑到这一点:C++ c++;在通知父级的同时删除树结构中的所有子级,c++,list,C++,List,考虑到这一点: class A { public: A() ~A() void add(A *child); void remove(A *child); void set_parent(A *parent); private: A *parent; std::list<A*> children; }; 实际上,我不想做任何更复杂的事情,但问题是,当删除列表的子项时,每个子项都会通知其父项它们现在已离开,从
class A {
public:
A()
~A()
void add(A *child);
void remove(A *child);
void set_parent(A *parent);
private:
A *parent;
std::list<A*> children;
};
实际上,我不想做任何更复杂的事情,但问题是,当删除列表的子项时,每个子项都会通知其父项它们现在已离开,从而操纵我们当前迭代的列表。你能做什么?在删除子项之前先“分离”父项如何
A::~A() {
//Keep the hierarchy clean and inform parent that we are gone now
if(this->parent != nullptr) {
this->parent->remove(this);
}
//Also delete all children as they would be lost now ...
for(A *child : children) {
child->set_parent(nullptr); // Detach parent to avoid re-calling remove()
delete child;
}
}
在删除子项之前先“分离”父项如何
A::~A() {
//Keep the hierarchy clean and inform parent that we are gone now
if(this->parent != nullptr) {
this->parent->remove(this);
}
//Also delete all children as they would be lost now ...
for(A *child : children) {
child->set_parent(nullptr); // Detach parent to avoid re-calling remove()
delete child;
}
}
您可以通过不迭代析构函数中的
列表来避免此问题。相反,只要还有子项,就删除子项
A::~A() {
//Keep the hierarchy clean and inform parent that we are gone now
if(this->parent != nullptr) {
this->parent->remove(this);
}
//Also delete all children as they would be lost now ...
while(children.empty() == false)
{
delete children.back();
}
}
您可以通过不迭代析构函数中的列表来避免此问题。相反,只要还有子项,就删除子项
A::~A() {
//Keep the hierarchy clean and inform parent that we are gone now
if(this->parent != nullptr) {
this->parent->remove(this);
}
//Also delete all children as they would be lost now ...
while(children.empty() == false)
{
delete children.back();
}
}
我所能想到的最简单、最直接的解决方案是简单地使用一个布尔标志,当设置该标志时,remove
将什么也不做。在迭代列表之前设置此标志
然后我们有了一个实际上可能更好的解决方案:智能指针。然后您根本不需要析构函数中的循环,当列表对象本身被析构函数时,包含的指针将简单地“删除”它们自己。这是两个很好的参考资料,你可能想研究一下
那么最好的解决方案,IMO:将元素从析构函数中移除解耦。有一个从父元素中删除元素的显式函数,并且在析构函数中没有remove
调用。这与共享指针相结合,可能是最安全的处理方法。不过,您可能需要一些重新设计(可能还需要一些重构)。我能想到的最简单、最直接的解决方案是简单地使用一个布尔标志,当设置该标志时,remove
将什么也不做。在迭代列表之前设置此标志
然后我们有了一个实际上可能更好的解决方案:智能指针。然后您根本不需要析构函数中的循环,当列表对象本身被析构函数时,包含的指针将简单地“删除”它们自己。这是两个很好的参考资料,你可能想研究一下
那么最好的解决方案,IMO:将元素从析构函数中移除解耦。有一个从父元素中删除元素的显式函数,并且在析构函数中没有remove
调用。这与共享指针相结合,可能是最安全的处理方法。不过,您可能需要进行一些重新设计(可能还需要进行一些重构)。使用std::list
很容易删除并对其进行迭代,因为只有在删除相应的元素时,迭代器才会失效:
auto child = std::begin(children);
while(child != std::end(children))
{
auto next = child + 1;
delete *child;
child = next;
}
使用std::list
可以很容易地删除和迭代它,因为只有在删除相应的元素时,迭代器才会失效:
auto child = std::begin(children);
while(child != std::end(children))
{
auto next = child + 1;
delete *child;
child = next;
}
您也可以这样做:
for (auto it = children.begin(); it != children.end();)
{
(*it)->set_parent(nullptr)
delete *it;
it = children.erase(it);
}
您也可以这样做:
for (auto it = children.begin(); it != children.end();)
{
(*it)->set_parent(nullptr)
delete *it;
it = children.erase(it);
}
我没有将此添加到详细信息中,但现在集合家长还通知当前家长(如果有)孩子改变了自己的所有权,这就是为什么你应该在问题中加入所有最低相关信息,否则你可能会得到次优答案。无论如何,如果您也有办法“分离”该通知,它可能仍然有效。毕竟,您正在销毁孩子,告诉家长孩子正在更改家长没有任何有用的信息(改为nullptr,因为它正在分离)。对不起,我已经修复了它,为了您的“想法”,我添加了一个“如果新家长!=nullptr”对于集合父条件,我没有将其添加到详细信息中,但现在集合父条件也会通知当前父条件(如果有)子条件更改了其所有者这就是为什么您应该在问题中添加所有最低相关信息,否则您可能会得到次优答案。无论如何,如果您也有办法“分离”该通知,它可能仍然有效。毕竟,您正在销毁该子项,告诉父项该子项正在更改父项(为nullptr,因为它正在将其拆离)没有任何有用的信息。对不起,我已修复了它,出于您的“想法”,我在set\u parent条件中添加了一个“if new\u parent!=nullptr”