http://blog.csdn.net/wplxb/archive/2007/06/16/1654116.aspx 源文章地址
---------------------------------------------------------------------------
1. 寫出下面程序的輸出。
#include <stdio.h>
class abc;
void del(abc *pobj)
{
delete pobj;
}
class abc
{
public:
abc(){
printf("abc/r/n");
}
~abc(){
printf("~abc/r/n");
}
};
int main(int argc, char *argv[])
{
abc *pobj = new abc;
del(pobj);
}
答:
abc
說明:定義 del 函數的時候,abc 的析構函數未定義,因此不會調用。
---------------------------------------------------------------------------
2. 寫出下面程序的輸出。
#include <stdio.h>
#include <stdlib.h>
void * operator new(size_t size)
{
printf("malloc %u/r/n", size);
return malloc(size);
}
void operator delete(void * memblock)
{
printf("free/r/n");
return free(memblock);
}
class abc
{
public:
abc()
{
printf("abc/r/n");
throw int();
}
~abc()
{
printf("~abc/r/n");
}
};
int main(int argc, char * argv[])
{
try
{
new abc;
}
catch (int & i)
{
printf("%d/r/n", i);
}
return 0;
}
答:
malloc 1
abc
free
0
如果將“new abc;”換成“abc a;”,結果將是:
abc
0
說明:
1. 在 C++ 中,構造函數拋出異常後不會觸發析構函數的調用,這和 object pascal 不一樣。C++ 認爲構造失敗意味着對象沒有產生,既然沒有生就沒有死。然而,當構造函數拋出異常時,仍會調用 delete 函數以釋放內存。
operator new 重載全局 new,所以下面構造的時候 new 肯定會調用該 operator new。operator delete 同樣。因此先輸出 malloc 1。
new 分配完內存後,會自動調用構造函數,所以輸出 abc。
在構造函數內部,拋出異常,throw int();
這個異常被捕獲,輸出 i,其值爲 0。
但是在捕獲的異常被處理之前,必須先釋放內存。因爲異常出錯,但此時 new 分配內存的工作已經完成,如果不進行 delete 的話,勢必會內存泄露。
2. 當生成堆棧對象時,C++ 自動調用的 operator new 和 operator delete 是全局的 operator new 和 operator delete。
參考:
《More Effective C++》條款10: 在構造函數中防止資源泄漏
…… 不用爲 BookEntry 中的非指針數據成員操心,在類的構造函數被調用之前數據成員就被自動地初始化。所以如果 BookEntry 構造函數體開始執行,對象的 theName、theAddress 和 thePhones 數據成員已經被完全構造好了。這些數據可以被看做是完全構造的對象,所以它們將被自動釋放,不用你介入操作。……
---------------------------------------------------------------------------
3. 寫出下面程序的輸出。
#include <stdio.h>
template <typename T>
class abc{
public:
abc(){
printf("primary/r/n");
}
};
template<>
abc<int>::abc()
{
printf("member spec/r/n");
};
template<typename T, typename P>
class abc<T (*)(P)>
{
public:
abc(){
printf("partial spec/r/n");
}
};
int main(int argc, char *argv[])
{
abc<void* (*)(int)> f_abc;
abc<int> i_abc;
}
答:
partial spec
member spec
說明:模板部分特化。
---------------------------------------------------------------------------
4. 下面的代碼能否通過編譯?爲什麼?
class a
{
public:
virtual ~a()
{
}
private:
void operator delete(void *p);
};
int main(int argc, char *argv[])
{
a _1;
}
答:
不能
說明:
1) 如果一個類有虛析構函數的話,那麼自定義 delete 函數必須有函數體。
2) 這個題目中,並不會調用 delete 函數。
3) 對於本題,delete 函數不被調用,但是編譯器需要它,因此,不能沒有定義。
參考:
如果對象是動態創建(也就是 new 出來的),那麼在 delete 的時候系統會先調析構函數然後調 operator delete。編譯器在編譯的時候會把這 2 個步驟合併到一個函數裏,看反彙編就知道了,函數名字類似 'scalar deleting destructor'。如果只是聲明瞭 operator delete 函數而沒有定義,那麼編譯的時候會得不到函數地址,這樣生成 'scalar deleting destructor' 內置函數的時候就會報錯了。