【问题标题】:Is the correct type required for the delete operator in C++?C++ 中的删除运算符是否需要正确的类型?
【发布时间】:2011-11-27 07:45:36
【问题描述】:
void * intptr = new int;
delete (int *) intptr;

是否需要 (int *) 类型转换?

【问题讨论】:

  • 不是重复的。这个问题是关于在通过new[] 分配的东西上使用delete 删除指向除分配类型以外的类型的指针。在一个语句中两次调用未定义的行为。这里没有未定义的行为; new 匹配 delete 并且类型也匹配。
  • 请注意,这是一个删除 表达式,而不是运算符。因为实际上有一个删除操作符(operator delete/operator delete[]),所以区分很重要。

标签: c++ memory-management casting


【解决方案1】:

是的。

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

【讨论】:

  • 我持怀疑态度,但在标准中发现了这一点:[注意:这意味着 delete-expression 的语法必须与 new 分配的对象的类型匹配,而不是 new-expression 的语法. ——尾注]
  • 澄清一下:它需要匹配的唯一原因不是可以删除它,而是可以调用正确的析构函数。
【解决方案2】:

是的。由于 C++ 不是一种万物皆对象的语言,因此删除命令必须知道要删除的内容的类型才能知道如何删除它。

【讨论】:

  • 虽然这是正确的,但评论没有任何意义。无论如何,我看不出 int or and int* 不是 C++ 意义上的对象。
  • 将其与 C# 进行比较。在 C# 中,一切都是对象——所有数据类型都派生自 System.Object,因此可以共享通用方法。如果 C# 没有被垃圾回收,它可能在 System.Object 中有一个虚拟 d'tor,使其能够在不知道变量类型的情况下删除任何变量。在 C++ 中,每个引用都可以是 void*,但这并不意味着 void* 可以包含方法。如果 C++ 中的所有内容都是一个对象,那么 void* 就是一个对象引用,并且您可以在其上使用 delete(即使它没有虚拟 d'tor - 它会编译并工作,只是不会调用 d'tor代码...)
  • @someboddy:虽然不是简单的未装箱类型 :) 所以不是一切。
【解决方案3】:

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

没有“int 的析构函数”这样的东西。 delete/delete[] 只会为非 POD 或 POD 类类型的事物调用析构函数。

【讨论】:

    【解决方案4】:

    这是必需的,因为 delete 将为每个分配的元素调用一个析构函数,即使对于 int 也是如此。

    考虑一下:

    char * chars = new char[3];
    
    delete [] (int*)chars;
    

    会发生什么?将调用 int 的 3 个析构函数。第一个用于&chars[0] 的内存地址,第二个用于&chars[4],第三个用于&chars[8]。考虑&chars[4]&chars[8] 超出了分配内存的大小。即使int 析构函数在大多数(如果不是所有)编译器都是虚拟的,但它是错误的行为。想象一下,如果你写

    delete [] (Foo*)chars;
    

    其中Foo 有析构函数和sizeof(Foo) > sizeof(char)。您的程序的行为将是未定义的。

    【讨论】:

      猜你喜欢
      • 2015-09-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-03-29
      • 2013-02-06
      • 2013-02-21
      • 2021-07-29
      • 2015-10-23
      相关资源
      最近更新 更多