c++全域性建構函式和析構函式的呼叫機制
控制台exe中c++的全域性變數在main之前初始化,在main之後清除,vc編譯器、鏈結器和vc執行庫**互相配合完成了這個魔術。請複製這段**到你新建的控制台程式,建立並執行:
#include "stdafx.h"
#include
#define secname ".crt$xcu"
#pragma section (secname, long, read)
void cleanup()
void init()
typedef void (_cdecl *_pvfv) () ;
_declspec (allocate(secname)) _pvfv callb4main = ;
int main()
輸出結果:
hello
in main
bye
奇怪!你並沒有呼叫init和cleanup,但很明顯它們被呼叫了,這是怎麼回事呢?
我們知道真正的入口函式是maincrtstartup,對於我們的討論,maincrtstartup可簡化如下:
int __tmaincrtstartup()//這個函式會被鏈結進我們的exe,並作為入口點函式
// file: crt\src\crt0dat.c
static void _cdecl _initterm (_pvfv * pfbegin,_pvfv * pfend)
}
這就是呼叫建構函式的地方。對於我們定義的每乙個全域性變數,編譯器把它的構造函式呼叫(不管你帶多少引數)編譯成一段**(簽名格式為_pvfv),這段**同時用atexit註冊了析構函式(對於編譯器這是很容易的)。然後把這段**的函式指標放入乙個_pvfv陣列。鏈結器把這些_pvfv陣列連成乙個大陣列。
_initterm引數中的pfbegin就指向這個陣列的第乙個元素,pfend指向這個陣列的最後乙個元素(總為null),我們的建構函式就這樣被呼叫了,這也是上面的魔術的工作原理。atexit註冊的函式將在main之後exit(與_initterm**相似)中執行,而且遵循lifo的原則,所以析構函式會按照和建構函式相反的順序呼叫。
對於非控制台exe和dll,情形是類似的。
任何使用者態程序的真正的入口其實是kernel32.dll!_baseprocessstart@4,但這與我們的討論無關。
《程式設計師的自我修養--裝載、鏈結和庫》
C 全域性物件構造和析構
注 此為小白引導教程 引入 c 中的全域性物件什麼時候執行建構函式?什麼時候執行析構函式?與區域性物件又有什麼區別?正文 思路是這樣的,我們先寫乙個類,乙個有點簡單 又不簡單 的類 include include using std string using std cout using std e...
深度剖析空間配置器(一)構造和析構函式
頻繁的申請和釋放,就會頻繁的呼叫malloc函式和free函式 呼叫函式會壓棧出棧,這些都是有開銷的 這就會造成,即使是有足夠的記憶體 40位元組 但是通過申請並不能得到乙個連續24位元組的記憶體 從而引入了空間配置器 空間介面卡是stl,標準模板庫的六大元件之一,其餘分別是 容器,迭代器,演算法,...
C 的全域性構造與析構函式
我們知道一般的c c 的程式是從main函式開始的,然後在main函式結束後程式結束。但是不然,在main函式開始執行前,已經有其他的指令被執行了。為了程式的順利執行,首先要初始化執行環境,比如堆分配初始化 malloc,free 執行緒子系統等,這裡先提一下 c 的全域性物件建構函式就是在這一時期...