class C {
public:
std::vector<C*> list;
int value;
C(int value, C* parent)
{
this->value = value;
if(parent)
{
parent->registerChild(this);
}
}
void registerChild(C* child)
{
this->list.push_back(child);
}
~C()
{
for(std::vector<C*>::iterator it = list.begin(); it != list.end(); ++it)
{
if( (*it))
{
delete (*it);
}
}
}
};
这是一个GUI项目。具有父级的子类必须通知它的父类,以便在删除父类时,也应删除其所有子类。
C* main = new C(100, 0);
C* child1 = new C(250, main);
C* child2 = new C(450, main);
delete main;
^一切按预期工作 - main与child1和child2一起删除。
C* main = new C(100, 0);
C* child1 = new C(250, main);
C* child2 = new C(450, main);
delete child1;
delete main; // windows error
如果我决定首先摆脱child1然后稍后决定删除main,我会得到一个Windows错误,它会追溯到矢量循环,显然删除尝试删除现在不存在的指针。 我会想如果((* it))对于一个不再存在的指针会返回false。
我可以在这做什么?
编辑: 这看起来完美无缺
class C {
typedef std::vector<C*> cList;
public:
std::vector<C*> list;
int value;
C* parent;
C(int value, C* parent)
{
this->value = value;
this->parent = parent;
if(parent)
{
parent->registerChild(this);
}
}
void registerChild(C* child)
{
this->list.push_back(child);
}
void removeChild(C* child)
{
cList::iterator it = std::find(list.begin(), list.end(), child);
if(it != list.end())
{
list.erase(it);
}
}
~C()
{
if(this->parent)
{
// this child is being removed - notify parent and remove this from its child_list
this->parent->removeChild(this);
}
cList::iterator it = list.begin();
while(it != list.end())
{
delete (*it);
// find a new beginning
it = list.begin();
};
}
};
答案 0 :(得分:3)
当您致电delete main
时,会在其子女身上致电delete
。 child1
就是其中之一。所以你在同一个内存地址上调用delete
两次。那是未定义的行为。
我原以为
if( (*it))
会因为不再存在的指针而返回false。
不,没有机制让一个指针知道它指向的对象已被另一个指针删除。
我可以在这做什么?
确保只有一个实体负责管理动态分配的对象。
答案 1 :(得分:0)
这是一种半广泛的错误概念,当指针被指向的内存被删除时,指针被设置为NULL。它不是。此外,删除NULL是安全的,因此在删除之前检查指针是否为NULL(主题...)。
答案 2 :(得分:0)
指针没有什么神奇之处。它们(通常是)机器字宽的整数,可用于指代特定的存储器地址。当它所提到的内存区域不再由您的程序拥有时,没有任何魔法可以使整数为NULL。
处理像这样的原始指针是一个坏主意。人们很容易被谁负责管理指向的内存所迷惑。
查看std :: unique_ptr和std :: shared_ptr(http://en.cppreference.com/w/cpp/memory)。
考虑将父指针保持为类的成员,添加注销成员函数。然后在类的析构函数中,让对象从父对象中取消注册。您需要更改管理子窗口列表的方式。
此外,您的类成员变量的名称确实应该更具描述性。 list
并没有告诉我们什么。考虑使用children
或child_list
这样的名称。