C++ c++;删除不存在的指针

C++ c++;删除不存在的指针,c++,pointers,C++,Pointers,^一切都按预期进行-main与child1和child2一起被删除 C* main = new C(100, 0); C* child1 = new C(250, main); C* child2 = new C(450, main); delete main; 如果我决定先去掉child1,然后在稍后某个时候决定删除main,我会得到一个windows错误,它可以追溯到向量循环,显然delete试图删除一个现在不存在的指针。 我本以为如果((*it))会为一个不再存在的指针返回false

^一切都按预期进行-main与child1和child2一起被删除

C* main = new C(100, 0);

C* child1 = new C(250, main);
C* child2 = new C(450, main);

delete main;
如果我决定先去掉child1,然后在稍后某个时候决定删除main,我会得到一个windows错误,它可以追溯到向量循环,显然delete试图删除一个现在不存在的指针。 我本以为如果((*it))会为一个不再存在的指针返回false

我能在这里做什么

编辑: 这似乎工作完美无瑕

C* main = new C(100, 0);

C* child1 = new C(250, main);
C* child2 = new C(450, main);

delete child1;

delete main; // windows error
C类{
typedef std::向量cList;
公众:
std::向量表;
int值;
C*父母;
C(int值,C*父级)
{
这个->值=值;
这->父=父;
如果(家长)
{
父项->注册子项(此项);
}
}
无效注册表子项(C*子项)
{
此->列表。推回(子项);
}
void removeChild(C*子级)
{
cList::iterator it=std::find(list.begin(),list.end(),child);
if(it!=list.end())
{
删除(它);
}
}
~C()
{
如果(此->父级)
{
//正在删除此子项-通知父项并将其从其子项列表中删除
this->parent->removeChild(this);
}
cList::iterator it=list.begin();
while(it!=list.end())
{
删除(*它);
//重新开始
it=list.begin();
};
}
};

当您调用
delete main
时,它将对其子项调用
delete
child1
就是其中之一。因此,您对同一内存地址调用了两次
delete
。这是未定义的行为

我本以为,
if((*it))
会为不再存在的指针返回false

不,没有任何机制让一个指针知道它指向的对象已通过另一个指针删除

我能在这里做什么


确保只有一个实体负责管理动态分配的对象。

删除指针指向的内存时,指针被设置为空是一种半普遍的错误观念。事实并非如此。此外,删除NULL是安全的,因此在删除指针之前检查指针是否不是NULL是没有必要的(主题外…。

指针没有什么神奇之处。它们只是(一般来说)机器字宽度的整数,可以用来表示特定的内存地址。当它提到的内存区域不再属于您的程序时,没有什么魔法可以使该整数为空

像这样处理原始指针是个坏主意。人们很容易被谁负责管理指向的记忆所迷惑

查看std::unique_ptr和std::shared_ptr()

考虑将父指针保留为类的成员,添加一个注销成员函数。然后在类的析构函数中,让对象从父对象取消注册自身。您需要更改管理子窗口列表的方式


此外,类成员变量的名称应该更具描述性<代码>列表告诉我们的不多。考虑一个名字,例如“代码>儿童< /代码>或<代码>子目录> /COD>。 为什么不使用
unique_ptr
shared_ptr
?这可能是重复的,这就是为什么你不想删除仍然有指向它们的指针的东西,这也是存在各种形式的智能指针的主要原因之一。我应该提到我还没有在C++11上…@Athlon1600为什么你还没有在C++11上?您应该标记您所在的版本。
C* main = new C(100, 0);

C* child1 = new C(250, main);
C* child2 = new C(450, main);

delete child1;

delete main; // windows error
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();
        };
    }
};