C++中使用delete操作符需要正确的类型吗?

8
void * intptr = new int;
delete (int *) intptr;

需要进行 (int*) 类型转换吗?


1
可能是通过不同类型的指针删除缓冲区?的重复问题。 - Nemo
不是重复的问题。那个问题是关于在使用new[]分配的东西上使用delete 针对分配类型之外的指针进行删除的。一条语句中有两次未定义行为。这里没有未定义的行为; newdelete匹配,并且类型也匹配。 - David Hammen
1
请注意,这是一个删除表达式,而不是运算符。因为实际上有一个删除运算符(operator delete/operator delete[]),所以这个区别很重要。 - GManNickG
4个回答

12

是的。

类型必须与new时的类型匹配。唯一不需要匹配的情况是通过基指针删除派生类型的情况,其中基类型具有虚析构函数。


1
我曾持怀疑态度,但在标准中找到了这个说明:[注:这意味着delete表达式的语法必须与new分配的对象的类型匹配,而不是new表达式的语法。-注] - Pubby
1
只是为了澄清:需要匹配的唯一原因不是为了删除它,而是为了调用正确的析构函数。 - Mahmoud Al-Qudsi

5

是的。由于C ++不是一种完全面向对象的语言,因此删除命令必须知道您要删除的内容的类型,以便知道如何删除它。


2
虽然那是正确的,但这个注释没有任何意义。无论如何,我不明白为什么int或者int*在C++中不是一个对象。 - pmr
与 C# 相比,C++ 中的每个引用都可以是 void,但这并不意味着 void 可以包含方法。如果 C++ 中所有内容都是对象,那么 void* 就是对象引用,并且可以使用 delete 对其进行操作(即使它没有虚拟析构函数-它仍将编译和工作,只是不会调用析构函数代码...)。在 C# 中,一切都是对象-所有数据类型均源自 System.Object,因此可以共享公共方法。如果 C# 没有垃圾回收,它可以在 System.Object 中具有虚拟 d'tor,从而能够删除任何变量而无需知道其类型。 - Idan Arye
1
@someboddy:不过并不是简单的非装箱类型 :) 所以也不是所有东西。 - user405725

1

将调用3个int的析构函数。

并不存在“int的析构函数”这种东西。delete/delete[]只会为非POD或POD类类型调用析构函数。


0

这是必需的,因为即使是 int 类型,delete 操作也会为每个已分配元素调用析构函数。

考虑以下示例:

char * chars = new char[3];

delete [] (int*)chars;

会发生什么?3个int的析构函数将被调用。第一个是&chars[0]的内存地址,第二个是&chars[4],第三个是&chars[8]。请注意,&chars[4]&chars[8]超出了分配内存的大小。即使在大多数编译器中,int的析构函数是虚函数,但这是错误的行为。想象一下如果你写了这样的代码。

delete [] (Foo*)chars;

如果 Foo 有析构函数且 sizeof(Foo) > sizeof(char),那么你的程序行为将是未定义的。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接