【问题标题】:Is it safe to delete static casted pointer?删除静态转换指针是否安全?
【发布时间】:2021-06-18 14:47:40
【问题描述】:

考虑抽象类AbstractMap,它是子类MyMap。执行以下删除操作是否安全?或者,我应该仅在重新投射到 MyMap 后删除 ptr 吗?为什么?我猜这是不安全的,因为在这种情况下MyMap 的析构函数没有被调用。

AbstractMap* ptr;
ptr = static_cast<AbstractMap*>(new MyMap());
delete ptr;

past question 谈到要转换为 void* 案例,但我不确定我的案例。

【问题讨论】:

  • 这取决于AbstractMap 是否准备好进行多态性。 (即它的析构函数是否被标记为虚拟)
  • 仅当 AbstractMap 具有虚拟析构函数时才允许。如果不是,则程序的行为未定义。
  • 在所描述的情况下不需要 static_cast。
  • @PeteBecker 谢谢!假设AbstractMap有一个虚析构函数,怎么调用子类的析构函数?我的意思是,假设我们还有很多AbstractMap 的子类,它怎么知道“原始”类是MyMap
  • 这就是virtual 的魔力。在所有情况下都会调用正确版本的函数。在幕后,这通常使用a "vtable" 实现。

标签: c++ pointers dynamic-cast static-cast


【解决方案1】:

考虑抽象类 AbstractMap 和它的子类 MyMap。 执行以下删除操作是否安全?

ptr = static_cast<AbstractMap*>(new MyMap());
delete ptr;

仅当基的析构函数(在本例中为AbstractMap)是虚拟的时,通过指向基子对象的指针删除才是安全的。如果不满足该前提条件,则程序的行为未定义。

假设AbstractMap有虚析构函数,怎么调用子类的析构函数?

请注意,如果您使用分配新表达式创建实例,那么您不应该直接调用析构函数。 delete 会为你做这件事。

但在可能需要直接调用析构函数的特殊情况下,您可以通过使用动态调度(这是虚函数的默认调度形式)调用AbstractMap 的析构函数来实现。

它怎么知道“原始”的是MyMap?

您不需要知道动态类型。这就是虚函数如此出色的原因。


附:避免拥有裸指针。几乎不需要写newdelete

【讨论】:

    【解决方案2】:

    如果AbstractMap 的(或它的基类,如果有的话)析构函数被标记为virtualdelete ptr 将是明确定义的。

    编译器将虚拟调用派生最多的析构函数(与任何虚拟函数一样),而后者又会非虚拟调用基类的析构函数。

    析构函数将拥有调用所有成员对象的析构函数所需的所有代码,并且在此过程结束时,内存将被回收回堆管理器(基于分配块的大小)。

    【讨论】:

      猜你喜欢
      • 2010-10-30
      • 1970-01-01
      • 1970-01-01
      • 2011-04-03
      • 1970-01-01
      • 2012-01-27
      • 2010-10-02
      相关资源
      最近更新 更多