当类的指针实例超出范围时,是否会调用析构函数?

时间:2015-10-02 09:18:27

标签: c++ destructor

以此代码为例:

  class MyClass
   {
   public:
  ~MyClass()
   {
     cout << "Destructor called\n";
    }
   };

  int main()
   {
      MyClass Testvar;
      //  destructer called for this
      MyClass *ptrvar;
      ptrvar = &Testvar;
      // but not for this
   }

这给我带来了很多困惑。上面的代码打印: 析构函数叫 只有一次。我在main中声明了两个MyClass实例,其中一个是MyClass类型的普通变量,另一个是指向普通变量的相同类型的指针。这里不需要析构函数(没有动态分配),但为了举例,我在类中定义了一个。因此,因为定义了两个类实例,所以应该两次调用析构函数。但是,当我运行此代码时,这不会发生。如果我删除指针并定义一个更正常的实例,程序将打印:

析构函数调用 析构函数叫

我的观察是当指针实例超出范围时,不会隐式调用析构函数。我是对的,还是只是遗漏了什么。

3 个答案:

答案 0 :(得分:5)

  

我在main

中声明了两个MyClass实例

不,你没有。您声明了MyClass的实例,并创建了指向该实例的指针。就是这样。

代码的行为是正确的。

  

我的观察是当指针实例超出范围时,不会隐式调用析构函数。我是对的,还是只是遗漏了什么。

没错。 C ++不提供garbage collector。你必须自己跟踪你的指针。您可以使用smart pointers来执行此操作。

答案 1 :(得分:3)

您只创建了一个对象,并且只为该对象调用了析构函数。

指针不实例化另一个对象,它只是指向前一个

当堆栈上分配的对象超出范围并且动态创建对象(使用operator new)被明确销毁(操作员删除)时,将调用析构函数

答案 2 :(得分:1)

您实际上只实例化了一个MyClass类型的对象。发生在这一行:

MyClass Testvar;

在以下行中,您只声明了指向MyClass类型对象的指针,但这不会创建新对象:

MyClass *ptrvar;

在这一行中,您将第一个MyClass的地址分配给指针:

ptrvar = &Testvar;

因此指针指向同一个对象,您仍然只有一个MyClass实例。范围关闭后,TestVar将被删除,您会看到析构函数被调用一次。

您可以在堆上创建一个新的MyClass对象,并将其地址分配给指针,如下所示:

MyClass *ptrvar = new MyClass();

现在你确实有两个MyClass个对象。但是,当范围关闭时,您仍然只能看到一个对象被删除。这是因为new在堆上而不是在堆栈上创建了一个对象,并且这些对象不会在创建它们的作用域的末尾自动删除。您必须使用delete手动执行此操作:

delete ptrvar;

当这一行执行时,你会看到你的析构函数被调用。如果你不这样做,你就会把你的对象留在堆上,并“泄露”它所占用的内存。

为了省去必须手动执行所有操作,您应该使用C ++提供的内置智能指针。