类成员`B`的析构函数,为什么在下面的代码片段中调用它?

时间:2015-06-10 18:07:32

标签: c++ language-lawyer c++14 delete-operator

从§5.3.5[expr.delete] / 1,我可以理解对象*a的析构函数在下面的代码段中被而不是调用。但我不明白为什么在这种情况下会调用类成员B的析构函数,如live example中所示。

#include <iostream>
class A
{
public:
   class B{ public: ~B(){ std::cout << "B dtor" << '\n'; } };
   A() { p = new B(); }
   operator B*() { return p; }
private:
   B* p;
};

int main()
{
   A* a = new A();
   delete *a;
   std::cout << "end" << '\n';
}

非常感谢标准中的一些引用解释这一点。

2 个答案:

答案 0 :(得分:13)

您的delete *a将运营商delete应用于*a类型的非指针表达式A。唯一可以合法的方法是类型A可以隐式转换为某种指针类型。

  

5.3.5删除[expr.delete]

     

1 ...操作数应具有指向对象类型的指针,或具有单个非显式转换的类类型   函数(12.3.2)指向对象类型的指针。

     

2 如果操作数有   类类型,操作数通过调用转换为指针类型   上述转换函数,使用转换后的操作数   代替本节其余部分的原始操作数。

在这种情况下,您的班级A可隐式转换为B *,这正是您执行delete *a时所发生的情况。

换句话说,您的delete *a实际上被解释为

delete (*a).operator B*();

代码中B delete,而不是A。这就是调用B的析构函数的原因。

如果你想销毁A对象,你必须做

delete a;

(注意,没有*)。那不会叫B的析构函数。

答案 1 :(得分:0)

如果您尝试实现智能指针 - 那么您可能应该检查boost sources

简而言之,智能指针模式提供了一些小对象的概念,即包装原始对象并在不需要时将其销毁。

例如非常简单的示例,也没有自定义删除器等等:

<template class T>
class scope_delete
{
 public:
   scope_delete(T* ptr) : p(ptr) {}
   ~scope_delete() { delete p; }
   T* operator->() { return p; }
 private:
   T * p;
};

// somewere in programm
{
  auto obj = scope_delete(new MyCLasss);
  obj->some_fun();
} // here stack object obj will be deleted and remove original object.

有关详细信息,您应该阅读一些书籍,或者我只是谷歌这个article