删除void指针是否保证删除正确的大小?

时间:2012-10-06 17:03:49

标签: c++ pointers memory-management void

  

可能重复:
  Is it safe to delete a void pointer?

假设我对名为new的类进行了MyClass分配,并且分配非常简单:

MyClass *myClassPtr = new MyClass();

我存储了对void*列表的引用,我只想说

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

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

delete myClassPtr

我用:

delete MyListOfPointer.get(0)

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

所以我不能做任何事情:

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

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

注意:
我不是在找任何指向智能指针的答案。

4 个答案:

答案 0 :(得分:14)

通过void*删除会导致未定义的行为,因此无法保证。

  

5.3.5删除[expr.delete]

     

1 delete-expression运算符销毁由new-expression创建的派生最多的对象(1.8)或数组   [...]
  操作数应具有指向对象类型的指针,或具有单个非显式转换函数(12.3.2)到指向对象类型的指针的类类型。结果类型为void。 78

     

78)这意味着无法使用void *类型的指针删除对象,因为void不是对象类型。

强调我的。


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

答案 1 :(得分:2)

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

答案 2 :(得分:1)

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

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

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(); }

答案 3 :(得分:0)

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

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