首页 文章

删除void指针是否保证删除正确的大小? [重复]

提问于
浏览
9

可能重复:删除空指针是否安全?

假设我有一个名为 MyClass 的类的 new 分配,分配就像:

MyClass *myClassPtr = new MyClass();

我将参考文献存储在 void* 列表中

myListOfPointers.add(static_cast<void*>(myClassPtr)); // this has to be void*

后来我释放内存而不是做:

delete myClassPtr

我用:

delete MyListOfPointer.get(0)

(假设myClassPtr引用是零索引 . )另外,请注意它必须是 void* ,因为这个列表可以存储不同类型的指针,所以我不知道我要删除的指针类型:

So I can't do any thing like:

delete static_cast<MyClass*>(MyListOfPointer.get(0))

这种方式是否会释放正确的内存大小? ( sizeof(MyClass) )?

Note:
我不是在寻找指向智能指针的任何答案 .

4 回答

  • 0

    通过 void* 删除会导致未定义的行为,因此您无需担保 .

    5.3.5删除[expr.delete] 1 delete-expression运算符销毁由new-expression创建的派生程度最高的对象(1.8)或数组 . [...]操作数应具有指向对象类型的指针,或具有指向对象类型的指针的单个非显式转换函数(12.3.2)的类类型 . 结果的类型为void.78 78)这意味着无法使用void *类型的指针删除对象,因为void不是对象类型 .

    强调我的 .


    所以即使你说不说,答案是创建某种形式的智能指针 . 它需要使用类型擦除来从外部隐藏类型(允许异构列表),但在内部跟踪它给出的类型以及如何删除它 . 像 boost::any 的东西很像 .

  • 1

    void 指针没有类型信息 . 如果 MyClass 有析构函数,则不会调用它 . 编译器需要知道它正在删除什么,以便它可以生成适当的代码 . 如果列表中的所有指针都是相同的类型,那么您应该将该类型存储在列表中,而不是 void . 如果指针是不同类型但派生自公共基类型,则为该基类型赋予虚拟构造函数并存储该类型的指针 .

  • 2

    没有必要使用智能指针,它只是聪明 .

    话虽如此,还有许多其他可能性;唯一要做的是沿着实际对象存储类型信息 .

    class Holder {
    public:
        template <typename T>
        explicit Holder(T const volatile* t):
            _data(static_cast<void const volatile*>(t)),
            _delete(&Delete<T>)
        {}
    
        void apply() { _deleter(_data); }
    
    private:
        typedef void (*Deleter)(void const volatile*);
    
        template <typename T>
        static void Delete(void const volatile* p) {
            delete static_cast<T const volatile*>(p);
        }
    
        void const volatile* _data;
        Deleter _deleter;
    };
    

    现在:

    std::list<Holder> owningList;
    
    owningList.push_back(Holder(somePointer));
    
    for (Holder& h: owningList) { h.apply(); }
    
  • 14

    这个问题的正确答案当然是'不'

    编辑:要求提供更多信息,即使我已经在对问题的评论中做了,删除void *是未定义的,这个问题是另一种问这个问题的方式:Is it safe to delete a void pointer? - 请参阅那里的答案以获取详细信息 .

相关问题