【问题标题】:c++ deleting non-existing pointersc++ 删除不存在的指针
【发布时间】:2014-04-18 16:44:24
【问题描述】:
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 错误,该错误可追溯到向量循环,显然 delete 试图删除一个现在不存在的指针。 我原以为 if( (*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();
        };
    }
};

【问题讨论】:

  • 为什么不使用unique_ptrshared_ptr
  • 这就是为什么你不想删除仍然有指向它们的东西的原因,也是存在各种形式的智能指针的主要原因之一。
  • 我可能应该提到我还没有使用 C++11...
  • @Athlon1600 为什么你还没有使用 C++11?您应该标记您所在的版本。

标签: c++ pointers


【解决方案1】:

当您调用 delete main 时,它会在其子代上调用 deletechild1 就是其中之一。所以你在同一个内存地址上调用delete 两次。这就是未定义的行为

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

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

我可以在这里做什么?

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

【讨论】:

    【解决方案2】:

    当指针指向的内存被删除时,指针被设置为 NULL 是一种半广泛的误解。它不是。此外,删除 NULL 是安全的,因此在删除指针之前检查指针是否不是 NULL 是不必要的(离题...)。

    【讨论】:

      【解决方案3】:

      指针没有什么神奇之处。它们只是(一般而言)机器字宽的整数,可用于引用特定的内存地址。当它提到的内存区域不再由您的程序拥有时,将该整数设为 NULL 并没有什么神奇之处。

      像这样处理原始指针是个坏主意。人们太容易混淆谁负责管理所指向的内存。

      查看 std::unique_ptr 和 std::shared_ptr (http://en.cppreference.com/w/cpp/memory)。

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

      此外,您的类成员变量的名称确实应该更具描述性。 list 并没有告诉我们太多。考虑像@​​987654323@ 或child_list 这样的名称。

      【讨论】:

        猜你喜欢
        • 2019-03-31
        • 1970-01-01
        • 2010-09-08
        • 2018-05-14
        • 1970-01-01
        • 1970-01-01
        • 2017-03-01
        • 2013-08-12
        相关资源
        最近更新 更多