linux c/c++面試知識點整理(一)

1、c/c++申請動態內存

? ? ? ?在c++中,申請動態內存是使用new和delete,這兩個關鍵字實際上是運算符,并不是函數。
? ? ? ?而在c中,申請動態內存則是使用malloc和free,這兩個函數是c的標準庫函數,使用它們必須包含stdlib.h,才能編譯通過。
? ? ? ?new/delete和malloc/free的相同之處在于,new和malloc都是手動申請動態內存,釋放時new則需要delete釋放內存,而malloc則需要free釋放內存。
? ? ? ?它們的不同之處在于,new和delete會自動調用對象的構造和析構函數,而malloc/free則只申請內存。
? ? ? ?另外需要注意的是:new的不是數組的話,則直接delete就好,并且只會調用一次析構函數,而new[]的話,則需使用delete[]來釋放,并且數組中每一個元素都會調用一次析構函數,調用完析構函數再釋放內存。
demo如下:

#include <stdlib.h>  //malloc用到
#include <string.h>  //memset用到
#include <stdio.h>   //printf用到

int main()
{
    //malloc/free使用
    int *pmalloc = (int*)malloc(sizeof(int)*4);
    //注意malloc分配的內存一定要進行初始化,否則會出現一些奇怪的問題的哦
    memset((void*)pmalloc, 0, sizeof(int)*4);
    for(int i = 0; i < 4; i++)
    {
        pmalloc[i] = i;
        printf("pmalloc[%d]=%d\n", i, pmalloc[i]);
    }
    free(pmalloc);

    //new/delete使用
    int *pNew = new int;
    *pNew = 3;
    printf("pnew = %d\n", *pNew);
    delete pNew;

    //new[]/delete[]使用
    int *pNewEx = new int[4];
    for(int i = 0; i < 4; i++)
    {
        pNewEx[i] = i;
        printf("pNewEx[%d] = %d\n", i, pNewEx[i]);
    }
    //此處的[]千萬不能掉,否則會導致內存泄露的
    delete[] pNewEx;

    return 0;
}

2、c++繼承是什么以及它的優缺點

什么是繼承?
? ? ? ?顧名思義,繼承是一種物體對另外一種物體某些屬性,動作的接續。舉個例子,比如人這個個體,它的屬性包括身高,體重等這些,它的動作則包括吃飯,喝水等等,那么如果另外要定義兩種物體,男人和女人,那么這些屬性和動作就都可以從人這個物體中繼承下來,這,就是繼承。當然,繼承不只是這么簡單,我們后續會陸續說到的。
demo如下:

#include <stdio.h>

class CPerson
{
public:
    CPerson()
    {
        height = 170;
        weight = 120;
    }
    ~CPerson(){}

    void DrinkWater()
    {
        printf("喝水\n");
    }

    void HavingDinner()
    {
        printf("吃飯\n");
    }

    int GetHeight()
    {
        return height;
    }

    int GetWeight()
    {
        return weight;
    }

private:
    int height;
    int weight;

};

class CMan : public CPerson
{
public:
    CMan(){}
    ~CMan(){}
};

class CWoman: public CPerson
{
public:
    CWoman(){}
    ~CWoman(){}

};

int main()
{
    CMan cMan;
    cMan.DrinkWater();
    cMan.HavingDinner();
    printf("男人身高:%d\n", cMan.GetHeight());
    printf("男人體重:%d\n", cMan.GetWeight());

    CWoman cWoman;
    cWoman.DrinkWater();
    cWoman.HavingDinner();
    printf("女人身高:%d\n", cWoman.GetHeight());
    printf("女人體重:%d\n", cWoman.GetWeight());

    return 0;
}
  • 優點:類繼承是在編譯時刻靜態定義的,且類繼承可以較方便地改變父類的實現,實現函數的重用。
  • 缺點:首先,因為繼承在編譯時刻就定義了,所以無法在運行時改變從父類繼承的實現,其次,父類一般至少定義了子類的部分行為,父類的任何改變都可能影響子類的行為,也就是說,如果繼承下來的實現不適合子類的問題,那么父類必須重寫或者被其他的類替換,這種依賴關系限制了靈活性。

從以上對比看,同一種屬性既可以是優點,從另外的方面來講,又是缺點,就看個人在編程過程中的靈活運用了。

3、c++的三大特性

? ? ? ?封裝、繼承、多態。

  • 封裝是一種技術,它使類的定義和實現分離;
  • 繼承,從廣義上講,繼承有三種實現方式,其一,為實現繼承,指使用基類的屬性和方法而無需額外編碼,其二,可視繼承,即子窗體使用父窗體的外觀和實現代碼,其三,則為接口繼承,即僅僅繼承屬性和方法,實現則滯后到子類去實現,也就是父類使用的是純虛函數,或者重寫父類接口方法,則是虛函數,例如多態的實現就使用了接口繼承。
  • 多態,簡單來講,就是父類定義了虛函數,子類重新實現該函數,那么當父類指針指向子類時,會調用子類的該方法,這,就是多態。
    下面是多態的demo:
#include <stdio.h>
#include <string.h>

class CPerson
{
public:
    CPerson()
    {
        height = 170;
        weight = 120;
        memset(sex, 0, sizeof(sex));
    }
    ~CPerson(){}

    virtual void SetSex() = 0;
    void PrintSex()
    {
        printf("我的性別是:%s\n", sex);
    }

private:
    int height;
    int weight;
//此處sex不能是私有,否則子類中無法使用,因為子類對父類的私有成員有繼承權,但沒有使用權,也就是只能看,不能摸
protected:
    char sex[8];

};

class CMan : public CPerson
{
public:
    CMan(){}
    ~CMan(){}

    void SetSex()
    {
        strncpy(sex, "男人", sizeof(sex)-1);
    }
};

class CWoman: public CPerson
{
public:
    CWoman(){}
    ~CWoman(){}

    void SetSex()
    {
        strncpy(sex, "女人", sizeof(sex)-1);
    }

};

int main()
{
    CPerson* pPerson = new CMan;
    pPerson->SetSex();
    pPerson->PrintSex();
    delete pPerson;

    CPerson* pPerson0 = new CWoman;
    pPerson0->SetSex();
    pPerson0->PrintSex();
    delete pPerson0;

    return 0;
}

4、子類和父類調用構造函數和析構函數的先后順序

  • 子類對象定義時,先調用父類的構造函數,再調用子類的構造函數;
  • 子類對象銷毀時,如果父類析構函數是虛函數,那么先調用子類的析構函數,再調用父類的析構函數,否則只會調用父類的析構函數;
    demo如下:
#include <stdio.h>

class CPerson
{
public:
    CPerson()
    {
        printf("建立父類\n");
    }
    //注意,父類析構函數一定要是虛函數,這樣銷毀子類時才會先調用子類的析構函數
    virtual ~CPerson()
    {
        printf("銷毀父類\n");
    }
};

class CMan : public CPerson
{
public:
    CMan()
    {
        printf("建立子類\n");
    }
    ~CMan()
    {
        printf("銷毀子類\n");
    }
};

int main()
{
    CPerson* pPerson = new CMan;
    delete pPerson;

    return 0;
}
執行結果如下:
建立父類
建立子類
銷毀子類
銷毀父類

5、什么是引用

引用,其實就是給變量取了一個別名,聲明引用時要切記初始化,且引用本身不占存儲單元,純粹就是變量多了一個名稱而已。
demo如下:

#include <stdio.h>

void setValue(int & p_iValue)
{
    p_iValue = 10;
}

void setValue1(int p_iValue)
{
    p_iValue = 9;
}

int main()
{
    int iValue = 8;
    int iValue1 = 8;
    setValue(iValue);
    printf("value=%d\n", iValue); //結果為10
    setValue1(iValue1);
    printf("value1=%d\n", iValue1); //結果還是8

    return 0;
}

6、將引用作為函數參數有哪些特點

  • 一是,使用引用傳遞參數是直接對實參本身進行操作,當需要在函數內部修改傳遞進來的變量并傳出去時,可使用引用;
  • 二來,引用是無需重新分配存儲空間的,但指針卻需要,所以有時使用引用會更有效率;

7、什么時候需要使用常引用

? ? ? ?當既要使用引用提高程序的效率,又不能在函數內部修改實參的值時,可使用常引用。

8、將引用作為函數返回值類型的好處和需遵循的規則

? ? ? ?好處:在內存中不產生被返回值的副本
? ? ? ?需遵循的規則:
? ? ? ?(1)不能返回局部變量的引用;
? ? ? ? (2)不能返回函數內部動態分配的變量的引用,因為引用只是作為一個臨時變量的出現,并未賦予一個實際的變量,該引用所指向的空間無法被釋放;
? ? ? ?(3)可以返回類成員的引用,但最好是const類型;
? ? ? ?(4)為了保證連續使用流操作符(<< >>)重載返回值時,操作的是同一個對象,流操作符重載返回值應該聲明為引用
? ? ? ?(5)+-*/這四則運算符不能返回引用

9、引用和多態的關系

? ? ? ?引用是c++中另外一種實現多態的手段,與指針一樣,也是基類的引用可指向派生類的實例。
引用實現多態的demo如下:

#include <stdio.h>
#include <string.h>

class CPerson
{
public:
    CPerson()
    {
        height = 170;
        weight = 120;
        memset(sex, 0, sizeof(sex));
    }
    ~CPerson(){}

    virtual void SetSex()
    {
        strncpy(sex, "人", sizeof(sex)-1);
    }
    void PrintSex()
    {
        printf("我的性別是:%s\n", sex);
    }

private:
    int height;
    int weight;
//此處sex不能是私有,否則子類中無法使用,因為子類對父類的私有成員有繼承權,但沒有使用權,也就是只能看,不能摸
protected:
    char sex[8];

};

class CMan : public CPerson
{
public:
    CMan(){}
    ~CMan(){}

    void SetSex()
    {
        strncpy(sex, "男人", sizeof(sex)-1);
    }
};

int main()
{
    CMan cman;
    CPerson *pPerson = &cman;
    pPerson->SetSex();  //此處調用的是子類的SetSex
    pPerson->PrintSex(); 

    return 0;
}

10、引用和指針的區別

  • 指針通過某個指針變量指向某個對象后,對指針所指向的對象間接操作;
  • 引用本身就是變量的別名,所以對引用操作就是直接對所指向的變量進行操作;
  • 引用不會重新分配存儲空間,但指針卻需要重新分配存儲空間;
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • 1. C++基礎知識點 1.1 有符號類型和無符號類型 當我們賦給無符號類型一個超出它表示范圍的值時,結果是初始值...
    Mr希靈閱讀 18,031評論 3 82
  • 1. 結構體和共同體的區別。 定義: 結構體struct:把不同類型的數據組合成一個整體,自定義類型。共同體uni...
    breakfy閱讀 2,138評論 0 22
  • const 引用 const 引用是指向 const 對象的引用:const int ival = 1024;co...
    rogerwu1228閱讀 653評論 0 1
  • 收集非原創文章,如遇原作者,請私聊我,我會表明出處! 1--10 1. C++中什么數據分配在棧或堆,靜態存儲區以...
    Juinjonn閱讀 4,963評論 0 30
  • C++知識50問1、C和C++的區別?C++相對于C的優勢。答:C是C++的基礎,C++是C的超集。C是一個結構化...
    萌面大叔2閱讀 575評論 0 26