2

C++ 如何确保为堆栈分配的对象调用析构函数?当我如下分配动态内存时,析构函数(或指向它的指针)会发生什么:

class MyClass {
public:

  ~MyClass()
  {
    std::cout<<"Destructor called."<<std::endl;
  }  

  MyClass()
  {
    std::cout<<"Constructor called."<<std::endl;
  }

};

....................................................................

//Limit scope for example
{
  MyClass instance;
}

构造函数和析构函数都被调用。这里发生了什么?

4

6 回答 6

7

编译器在适当的位置插入对对象的析构函数的调用。

于 2009-09-01T13:02:08.947 回答
4

你不会想知道为什么会这样

{
  int i;
}

自动创建和销毁i,你会吗?C++ 做了很多工作来允许您创建行为就像内置类型一样的类型。就像内置类型一样,在 C++ 中(除了 Java 或 C#),这个

{
  MyClass instance;
}

不只是定义可能绑定到null某个实际对象的引用。它创建了一个实际的对象。

对象创建分为两个步骤:首先(在进入范围时)提供原始内存。然后(当遇到对象定义时)调用构造函数。对于内置类型,不调用构造函数。如果您不初始化内置变量,则它具有随机值。(实际上,在步骤 #1 中提供的内存中的位模式是什么。)对象删除也分两步进行:首先,调用析构函数(同样,不是针对内置函数),然后将内存返回到运行时系统。

(请注意,为堆栈变量提供和删除内存通常与增加/减少寄存器一样便宜。)

于 2009-09-01T13:58:22.450 回答
3

创建变量后立即调用构造函数。至于析构函数,编译器会在作用域的末尾发出代码来调用析构函数。要对此有所了解,请尝试使用“goto”或 switch/case 构造来过早退出范围,并观察编译器的抱怨。

于 2009-09-01T13:00:28.397 回答
3

是的,构造函数和析构函数都被调用了。更重要的是:

{
 MyClass instance;
 throw "exception";
}

在这个例子中,析构函数也被调用。这就是为什么我总是喜欢在堆栈上分配我的对象(或者至少用堆栈分配的监护人包装动态分配)。

于 2009-09-01T13:49:22.900 回答
1

调用构造函数是因为您正在创建一个对象。调用析构函数是因为您清理了该对象。请记住,在 C++ 中,在堆栈上声明的对象会在其包含范围消失时自动清理。

于 2009-09-01T13:00:03.030 回答
0

好吧,它并没有在构造函数之后调用析构函数。
它在程序即将终止时调用它。

int main() {
    MyClass obj;
    cout<<"testing....1"<<endl;
    cout<<"testing....2"<<endl;
    return 0;
}

答:

Constructor called.
testing....1
testing....2
Destructor called.
于 2009-11-05T07:12:05.063 回答