曾經被問到過這樣兩個問題:
1> 在C/C++中,怎樣在程序退出main函數後仍然進行一些操作,比如資源堆棧方面的清理?
2> 在C++程序中,我們要怎樣才能夠得到程序退出main後對象析構所需要的時間?
我們知道,在C++中,全局對象或者main域中對象的析構,是在退出main函數後進行的。所以對於問題1,我們可以在一個全局對象的析構函數中調用相關的函數來實現。但是,C語言不支持對象,所以這種方法對於C程序就無能爲力了。
對於問題2,我們可以通過對象的構造與析構來勉強實現這一功能。我們可以定義兩個類A,B,其中A的析構函數可以打印出當前時間,B的構造函數可以打印出當前時間,此外A,B什麼也不做。如果我們在所有全局對象的實例定義前定義A的一個實例,而在main函數退出 (return 0 )前定義B的一個實例,那麼這兩個時間的差就是我們所要的。
然而上述對問題2的解決是基於程序中沒有調用exit()函數,若否,對象b就不會被創建,我們也就不能得到想要的時間了。
其實C/C++的CRT中有一個回調函數atexit(...),可以用來註冊需要在程序exit的時候需要調用的函數,詳細請參考:
http://www.cprogramming.com/fod/atexit.html 或者C:/Program Files/Microsoft Visual Studio 8/VC/crt/src/atonexit.c:123 上述問題1可以完全通過atexit函數實現,而問題2則可以通過綜合atexit和對象的析構來完成。事實上,大多數winodws上的C++編譯器,就是通過使用atexit函數來完成全局對象的析構的。
以下代碼演示瞭如何atexit()和對象析構的調用次序,權當拋磚引玉。如果讀者對atexit意猶未盡,可以研讀C/C++的CRT源碼,或者參考俞甲子、石凡、潘愛民著的《程序員的自我修養--鏈接、裝載與庫》的13.3.3 "atexit實現"一節。
/*
* Demostrate the atexit() and class destructor usage for C++.
*/
#include <cstdio>
#include <cstdlib>
#include <string>
#include <ctime>
void fnExit0 (void)
{
printf("Exit function 0./n");
printCurrentTime();
}
void fnExit1 (void)
{
printf( "Exit function 1./n" );
}
void fnExit2 (void)
{
printf ( "Exit function 2./n" );
}
void printCurrentTime( void )
{
struct tm tmp;
time_t s = time(NULL);
localtime_s(&tmp, &s);
printf("Current time at %04d:%02d:%02d:%02d:%02d:%02d/n",
tmp.tm_year+1900, tmp.tm_mon+1, tmp.tm_mday, tmp.tm_hour,tmp.tm_min,tmp.tm_sec);
}
class A
{
public:
A( const char * className ) {
m_className = className;
printf( "A::A() for %s /n", m_className );
}
~A() {
printf( "A::~A() for %s /n", m_className );
double sum = 0;
const int N = 1 << 28;
for ( int i = 0; i < N; i++ ) {
sum += i * i;
}
}
const char *m_className;
};
class B
{
public:
B ( const char *className ) {
m_className = className;
atexit( fnExit0 );
printf( "A::B() for %s /n", m_className );
}
~B ( ) {
printf( "B::~B() for %s /n", m_className );
}
const char *m_className;
};
void funcInMain(void)
{
A aInMain( "aInMain" );
}
B global_B( "global_B" );
A global_A( "global_A" );
int _tmain(int argc, _TCHAR* argv[])
{
printf( "Entering main()/n" );
atexit( printCurrentTime );
atexit( fnExit1 );
A a1("a1");
funcInMain();
atexit( fnExit2 );
A a2("a2");
printf( "Exiting main()/n" );
return 0;
}