關於C++中析構函數和構造函數的調用時機:分情況討論

一句話總結

構造函數和析構函數的調用時機:先構造的後析構,後構造的先析構,它相當於一個棧,先進後出。

但是,並不是在任何情況下都是按照上面的原則進行處理。對象可以在不同的作用域中定義,可以有不同的存儲類別,這些都會影響調用構造函數和析構函數的時機。

幾種調用時機的總結(看完實踐下):

(0)在全局範圍中定義的對象(即在所有函數之外定義的對象),它的構造函數在文件中的所有函數(包括main()函數)執行之前調用。但是如果一個程序中有多個文件,而不同的文件中都定義了全局對象,則這些對象的構造函數的執行順序是不確定的。當main()函數執行完畢或調用exit函數時(此時程序終止),調用析構函數。

(1)如果定義的是局部自動對象(如在函數中定義對象),則在建立對象時調用其構造函數。如果函數被多次調用,則在每次建立對象時都要調用構造函數。在函數調用結束、對象釋放時先調用析構函數。

(2)如果在函數中定義靜態(static)局部對象,則只在程序第一次調用此函數建立對象時調用構造函數一次,在調用結束時對象並不釋放,因此也不調用析構函數,只在main函數結束或調用exit函數結束程序時,才調用析構函數。

下面是代碼:

#include<iostream>
#include<stdlib.h>
using namespace std;

class test
{
public:
	test(int val):a(val)
	{
		cout << "Constructor called and a = " << a << endl;
	}

	~test()
	{
		cout << "Destructor called and a = " << a << endl;
	}

	int a;
};

void fun()
{
	// 定義自動局部對象,定義時執行構造函數,函數結束後釋放,執行析構函數
	test a(300);

	// 定義靜態局部對象,在函數第一次調用時執行構造函數,此後再次運行fun()函數,並不會調用構造函數
	// 函數結束後,並不釋放,而是等到程序結束後,才執行析構函數
	static test b(400);
}

// 全局對象
test A(9999);

int main()
{
	//	自動局部對象 先構造,後析構
	test a(100);	

	//  自動局部對象 後構造,先析構
	test b(200);	

	// 第一次調用函數
	fun();

	// 第二次調用函數
	fun();

	return EXIT_SUCCESS;
}

以下是函數執行結果,慢慢品。。。
後面的註釋和空格是我加上去的,並不是函數執行打印

// 全局對象在main函數執行之前,調用構造函數
Constructor called and a = 9999

// main函數中聲明的對象依次執行構造
Constructor called and a = 100
Constructor called and a = 200

// 第一次執行fun函數,靜態局部對象執行構造,但在函數結束後,並不執行析構
Constructor called and a = 300
Constructor called and a = 400
Destructor called and a = 300

// 第二次執行fun函數,靜態局部對象不再執行構造,因爲已經構造過了,函數結束後,仍不執行析構
Constructor called and a = 300
Destructor called and a = 300

// main函數結束,main函數中聲明的對象依次執行析構,最後析構的是靜態局部對象
Destructor called and a = 200
Destructor called and a = 100
Destructor called and a = 400

// 全局對象在main函數結束之後,調用析構函數
Destructor called and a = 9999

內容參考:《後臺開發 核心技術與應用實踐》

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章