关于c ++:删除void指针是否保证删除正确的大小?

Does deleting void pointer guarantee to delete right size?

本问题已经有最佳答案,请猛点这里访问。

Possible Duplicate:
Is it safe to delete a void pointer?

假设我有一个new分配给一个名为MyClass的类,分配简单如下:

1
MyClass *myClassPtr = new MyClass();

我在这里简单地说

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

后来我释放了记忆,所以我不再做:

1
delete myClassPtr

我使用:

1
delete MyListOfPointer.get(0)

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

所以我不能做这样的事:

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

这样可以释放正确的内存大小吗?(sizeof(MyClass)号)?

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


通过void*删除会导致未定义的行为,因此您没有任何保证。

5.3.5 Delete [expr.delete]

1 The delete-expression operator destroys a most derived object (1.8) or array created by a new-expression.
[...]
The operand shall have a pointer to object type, or a class type having a single non-explicit conversion function (12.3.2) to a pointer to object type. The result has type void.78

78) This implies that an object cannot be deleted using a pointer of type void* because void is not an object type.

强调我的。

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


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


不需要使用智能指针,它只是智能指针。

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
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;
};

现在:

1
2
3
4
5
std::list<Holder> owningList;

owningList.push_back(Holder(somePointer));

for (Holder& h: owningList) { h.apply(); }


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

编辑:被要求提供更多信息,即使我已经在对问题的评论中做过,删除一个void*是未定义的,这个问题是询问这个问题的另一种方式:删除一个void指针是否安全?-有关详细信息,请参阅其中的答案。