C++面試題總結

1. 引用和指針的區別

  1. 指針是一個實體,需要分配內存空間。引用只是變量的別名,不需要分配內存空間。
  2. 引用在定義的時候必須進行初始化,並且不能夠改變。指針在定義的時候不一定要初始化,並且指向的空間可變。(注:引用的值不能爲NULL)
  3. 多級指針,但是沒有多級引用,只能有一級引用。
  4. 指針和引用的自增運算結果不一樣。(指針是指向下一個空間,引用時引用的變量值加1)
  5. sizeof 引用得到的是所指向的變量(對象)的大小,而sizeof 指針得到的是指針本身的大小。
  6. 引用訪問一個變量是直接訪問,而指針訪問一個變量是間接訪問。
  7. 使用指針前最好做類型檢查,防止野指針的出現;
  8. 引用底層是通過指針實現的;
  9. 作爲參數時也不同,傳指針的實質是傳值,傳遞的值是指針的地址;傳引用的實質是傳地址,傳遞的是變量的地址。

2. C++中的值傳遞   指針參數傳遞   和   引用參數傳遞

  1. 值傳遞是最常規的C語言傳參方式。
    形參是實參的拷貝,改變形參的值並不會影響外部實參的值。
    從被調用函數的角度來說,值傳遞是單向的(實參->形參),參數的值只能傳入,不能傳出。
    當函數內部需要修改參數,並且不希望這個改變影響調用者時,採用值傳遞。
  2. 指針參數傳遞本質上是值傳遞,它所傳遞的是一個地址值。值傳遞過程中,被調函數的形式參數作爲被調函數的局部變量處理,會在棧中開闢內存空間以存放由主調函數傳遞進來的實參值,從而形成了實參的一個副本(替身)。        值傳遞的特點是,被調函數對形式參數的任何操作都是作爲局部變量進行的,不會影響主調函數的實參變量的值(形參指針變了,實參指針不會變)。
  3. 引用參數傳遞過程中,被調函數的形式參數也作爲局部變量在棧中開闢了內存空間,但是這時存放的是由主調函數放進來的實參變量的地址。被調函數對形參(本體)的任何操作都被處理成間接尋址,即通過棧中存放的地址訪問主調函數中的實參變量(根據別名找到主調函數中的本體)。因此,被調函數對形參的任何操作都會影響主調函數中的實參變量。

3.  形參與實參的區別?

  1. 形參變量只有在被調用時才分配內存單元,在調用結束時, 即刻釋放所分配的內存單元。因此,形參只有在函數內部有效。 函數調用結束返回主調函數後則不能再使用該形參變量。
  2. 實參可以是常量、變量、表達式、函數等, 無論實參是何種類型的量,在進行函數調用時,它們都必須具有確定的值, 以便把這些值傳送給形參。 因此應預先用賦值,輸入等辦法使實參獲得確定值,會產生一個臨時變量
  3. 實參和形參在數量上,類型上,順序上應嚴格一致, 否則會發生“類型不匹配”的錯誤。
  4. 函數調用中發生的數據傳送是單向的。 即只能把實參的值傳送給形參,而不能把形參的值反向地傳送給實參。 因此在函數調用過程中,形參的值發生改變,而實參中的值不會變化。
  5. 當形參和實參不是指針類型時,在該函數運行時,形參和實參是不同的變量,他們在內存中位於不同的位置,形參將實參的內容複製一份,在該函數運行結束的時候形參被釋放,而實參內容不會改變。

4. static的用法和作用?

  1. 先來介紹它的第一條也是最重要的一條:隱藏。(static函數,static變量均可)當同時編譯多個文件時,所有未加static前綴的全局變量和函數都具有全局可見性
  2. static的第二個作用是保持變量內容的持久。(static變量中的記憶功能和全局生存期)存儲在靜態數據區的變量會在程序剛開始運行時就完成初始化,也是唯一的一次初始化。共有兩種變量存儲在靜態存儲區:全局變量和static變量,只不過和全局變量比起來,static可以控制變量的可見範圍,說到底static還是用來隱藏的。
  3. static的第三個作用是默認初始化爲0(static變量)。

5. static的第四個作用:C++中的類成員聲明static 

  1. 函數體內static變量的作用範圍爲該函數體,不同於auto變量,該變量的內存只被分配一次,因此其值在下次調用時仍維持上次的值;
  2. 在模塊內的static全局變量可以被模塊內所用函數訪問,但不能被模塊外其它函數訪問;
  3. 在模塊內的static函數只可被這一模塊內的其它函數調用,這個函數的使用範圍被限制在聲明它的模塊內;
  4. 在類中的static成員變量屬於整個類所擁有,對類的所有對象只有一份拷貝;
  5. 在類中的static成員函數屬於整個類所擁有,這個函數不接收this指針,因而只能訪問類的static成員變量。

    類內:

  1. ​​​​​​​static類對象必須要在類外進行初始化,static修飾的變量先於對象存在,所以static修飾的變量要在類外初始化
  2. 由於static修飾的類成員屬於類,不屬於對象,因此static類成員函數是沒有this指針的,this指針是指向本對象的指針。正因爲沒有this指針,所以static類成員函數不能訪問非static的類成員,只能訪問 static修飾的類成員;
  3. static成員函數不能被virtual修飾,static成員不屬於任何對象或實例,所以加上virtual沒有任何實際意義;靜態成員函數沒有this指針,虛函數的實現是爲每一個對象分配一個vptr指針,而vptr是通過this指針調用的,所以不能爲virtual;虛函數的調用關係,this->vptr->ctable->virtual function

6. ​​​​​​​靜態變量什麼時候初始化

  1. 初始化只有一次,但是可以多次賦值,在主程序之前,編譯器已經爲其分配好了內存。
  2. 靜態局部變量和全局變量一樣,數據都存放在全局區域,所以在主程序之前,編譯器已經爲其分配好了內存,但在C和C++中靜態局部變量的初始化節點又有點不太一樣。在C中,初始化發生在代碼執行之前,編譯階段分配好內存之後,就會進行初始化,所以我們看到在C語言中無法使用變量對靜態局部變量進行初始化,在程序運行結束,變量所處的全局內存會被全部回收。
  3. 而在C++中,初始化時在執行相關代碼時纔會進行初始化,主要是由於C++引入對象後,要進行初始化必須執行相應構造函數和析構函數,在構造函數或析構函數中經常會需要進行某些程序中需要進行的特定操作,並非簡單地分配內存。所以C++標準定爲全局或靜態對象是有首次用到時纔會進行構造,並通過atexit()來管理。在程序結束,按照構造順序反方向進行逐個析構。所以在C++中是可以使用變量對靜態局部變量進行初始化的。

7.  const 的作用

  1. 阻止一個變量被改變,可以使用const關鍵字。在定義該const變量時,通常需要對它進行初始化,因爲以後就沒有機會再去改變它了;
  2. 指針來說,可以指定指針本身爲const,也可以指定指針所指的數據爲const,或二者同時指定爲const;
  3. 在一個函數聲明中,const可以修飾形參,表明它是一個輸入參數,在函數內部不能改變其值;
  4. 對於類的成員函數,若指定其爲const類型,則表明其是一個常函數,不能修改類的成員變量,類的常對象只能訪問類的常成員函數
  5. 對於類的成員函數,有時候必須指定其返回值爲const類型,以使得其返回值不爲“左值”。
  6. const成員函數可以訪問非const對象的非const數據成員、const數據成員,也可以訪問const對象內的所有數據成員;
  7. 非const成員函數可以訪問非const對象的非const數據成員、const數據成員,但不可以訪問const對象的任意數據成員;
  8. 一個沒有明確聲明爲const的成員函數被看作是將要修改對象中數據成員的函數,而且編譯器不允許它爲一個const對象所調用。因此const對象只能調用const成員函數。
  9. const類型變量可以通過類型轉換符const_cast將const類型轉換爲非const類型;
  10. const類型變量必須定義的時候進行初始化,因此也導致如果類的成員變量有const類型的變量,那麼該變量必須在類的初始化列表中進行初始化;
  11. 對於函數值傳遞的情況,因爲參數傳遞是通過複製實參創建一個臨時變量傳遞進函數的,函數內只能改變臨時變量,但無法改變實參。則這個時候無論加不加const對實參不會產生任何影響。但是在引用或指針傳遞函數調用中,因爲傳進去的是一個引用或指針,這樣函數內部可以改變引用或指針所指向的變量,這時const 纔是實實在在地保護了實參所指向的變量。因爲在編譯階段編譯器對調用函數的選擇是根據實參進行的,所以,只有引用傳遞和指針傳遞可以用是否加const來重載。一個擁有頂層const的形參無法和另一個沒有頂層const的形參區分開來。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章