C++ 使用不同类型的指针删除内存是否安全?

C++ 使用不同类型的指针删除内存是否安全?,c++,new-operator,heap-memory,delete-operator,C++,New Operator,Heap Memory,Delete Operator,以下代码安全吗?有没有提到C++标准来解决这个问题?< /P> // SomeStruct is POD: no constructors or destructor SomeStruct *pSS = new SomeStruct(); void *pV = reinterpret_cast<void*>(pSS); delete pV; //SomeStruct是POD:没有构造函数或析构函数 SomeStruct*pSS=新的SomeStruct(); void*pV=重新解

以下代码安全吗?有没有提到C++标准来解决这个问题?< /P>
// SomeStruct is POD: no constructors or destructor
SomeStruct *pSS = new SomeStruct();
void *pV = reinterpret_cast<void*>(pSS);
delete pV;
//SomeStruct是POD:没有构造函数或析构函数
SomeStruct*pSS=新的SomeStruct();
void*pV=重新解释铸件(pSS);
删除pV;
只有在以下情况下才可以:

  • 删除指向基的指针

  • 这个基类有一个虚拟析构函数

  • 否则,你将陷入非法代码和未定义行为的境地

    C++14 5.3.5/2

    如果操作数具有类类型,则通过调用上述转换函数将操作数转换为指针类型,并在本节的其余部分使用转换后的操作数代替原始操作数。在第一个备选方案(删除对象)中,
    delete
    的操作数值可以是空指针值、指向由以前的新表达式创建的非数组对象的指针,或者指向表示此类对象基类的子对象(1.8)的指针(第10条)。如果不是,则行为未定义。在第二种选择(删除数组)中,
    delete
    的操作数的值可以是空指针值,也可以是由以前的数组新表达式生成的指针值。如果不是,则行为未定义。[注:这意味着删除表达式的语法必须与
    new
    分配的对象类型相匹配,而不是与新表达式的语法相匹配。-结束注][注:指向常量类型的指针可以是删除表达式的操作数;无需丢弃常量(5.2.11)将指针表达式用作删除表达式的操作数之前的指针表达式的值。-结束注释]

    C++14 5.3.5/3

    在第一个备选方案(删除对象)中,如果要删除的对象的静态类型与其动态类型不同,则静态类型应为要删除的对象的动态类型的基类,并且静态类型应具有虚拟析构函数,或者行为未定义。在第二个备选方案(删除数组)中,如果要删除的对象的动态类型与其静态类型不同,则行为未定义

    此外,
    void
    是一个不完整的类型(C++14 3.9.1/9):

    void
    类型有一组空值。
    void
    类型是无法完成的不完整类型。它用作不返回值的函数的返回类型。任何表达式都可以显式转换为cv类型
    void
    (5.4)。
    void
    类型的表达式只能用作表达式语句(6.2)、逗号表达式(5.19)的操作数、
    ?:
    (5.16)的第二或第三个操作数、
    typeid
    的操作数、
    noexcept
    decltype
    ,以及返回语句(6.6.3)中的表达式对于返回类型为
    void
    的函数,或作为显式转换为cv
    void
    类型的操作数



    另外,除非您使用的是C API,
    void*
    是您应该努力避免的事情。

    它不仅是非法的,而且在现代编译器上只是一个编译错误。无法删除void*

    删除
    void*
    将不会调用原始对象的destructor@NathanOliver,这是可以的,因为pod处于焦点位置(请参见代码示例中的注释)。所以没有析构函数。我有相同的观点,但是至今还没有找到C++标准或FAQ中的基础。这不是一种意见;)MSVC++2013没有给我一个错误甚至警告(在警告级别4下编译)。我从来没有对这个编译器寄予厚望。@SergeyA:gcc 5.2.0或clang 3.5.1不是编译错误,只是警告而已。那些是“现代”编译器吗?