C++开发初级


848 浏览 5 years, 3 months

3.2 销毁对象

版权声明: 转载请注明出处 http://www.codingsoho.com/

销毁对象

当销毁对象的时候,会发生两件事:对象的析构函数被调用,释放对象占用的内存。在析构函数中可以执行对象的清理,例如释放动态分配的内存或者关闭文件句柄。如果您没有声明析构函数,编译器将自动生成一个,析构函数会逐一销毁成员然后删除对象。后面的动态内存分配小节将介绍如何编写析构函数。

当堆栈中的对象超出作用域时,意味着当前的函数、方法或者其他执行代码块结束,对象会被销毁。换句话说,当代码遇到结束花括号时,这个花括号中所有创建在堆栈上的对象都会被销毁。

下面的程序显示了这一行为:

int main()
{
  SpreadsheetCell myCell(5);

  if (myCell.getValue() == 5) {
    SpreadsheetCell anotherCell(6);
  } // anotherCell is destroyed as this block ends

  cout << "myCell: " << myCell.getValue() << endl;

  return 0;
} // myCell is destroyed as this block ends

代码取自 Destructors\DestructorExamples.cpp

堆栈上对象的销毁顺序与声明顺序(以及构建顺序)相反。例如,在下面的代码片段中,myCell2在anotherCell2之前分配,因此anotherCell2在myCell2之前被销毁(注意在程序中,可以使用左花括号在任意点开始新的代码块):

  {
    SpreadsheetCell myCell2(4);
    SpreadsheetCell anotherCell2(5); // myCell2 constructed before anotherCell2
  } // anotherCell2 destroyed before myCell2

代码取自 Destructors\DestructorExamples.cpp

如果某个对象是其他对象的数据成员,这一顺序也适用。数据成员初始化的顺序是它们在类中声明的顺序。因此,按照对象的销毁顺序与创建顺序相反这一规则,数据成员对象的销毁顺序与在类中声明的顺序相反。

在堆中分配的对象不会自动销毁。必须使用delete删除对象指针,从而调用析构函数并释放内存。下面的程序显示了这一行为:

int main()
{
  SpreadsheetCell* cellPtr1 = new SpreadsheetCell(5);
  SpreadsheetCell* cellPtr2 = new SpreadsheetCell(6);

  cout << "cellPtr1: " << cellPtr1->getValue() << endl;

  delete cellPtr1; // destroys cellPtr1
  cellPtr1 = nullptr;

  return 0;
} // cellPtr2 is NOT destroyed because delete was not called on it

代码取自 Destructors\DestructorHeapExamples.cpp

提示:不要编写与前面示例类似的程序,因为。cellPtr2没有被删除。一定要根据分配内存时使用的是new还是new[]相应地使用delete或者delete[]释放动态分配的内存,或者使用前面讲过的智能指针。

可以用工具检测没有被释放的对象,这些工具将在后面讨论。