C++的一些試題

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' 內置函數的時候就會報錯了。
 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章