C++基礎知識面試必備、複習細節 (3)

C++基礎知識面試必備、複習細節 (3)

vector擴容原理說明
  • 新增元素:Vector通過一個連續的數組存放元素,如果集合已滿,在新增數據的時候,就要分配一塊更大的內存,將原來的數據複製過來,釋放之前的內存,在插入新增的元素;
  • 對vector的任何操作,一旦引起空間重新配置,指向原vector的所有迭代器就都失效了 ;
  • 初始時刻vector的capacity爲0,塞入第一個元素後capacity增加爲1;
  • 不同的編譯器實現的擴容方式不一樣,VS2015中以1.5倍擴容,GCC以2倍擴容。
c++類型安全
  • c++遠比C更有類型安全性
  • c++的一些新的機制保障類型安全:
    • new返回的指針類型嚴格與對象匹配,而不是malloc返回的void*空類型指針
    • c++提供了dynamic_cast關鍵字,使得轉換過程更加安全
    • 引入const關鍵字代替#define constants,有類型和作用域,而#define constants是簡單的文本替換;
C++中四種類型轉換方式
轉換類型操作符 作用
static_cast 靜態類型轉換,類似於c的強制類型轉換。包括:基本的數據類型轉換,int到float等;
const_cast 去掉類型的const或volatile屬性
dynamic_cast 有條件轉換,動態類型轉換,運行時檢查類型安全(轉換失敗返回NULL) 通常用於基類和子類之間的轉換
reinterpret_cast 僅重新解釋類型,但沒有進行二進制的轉換,可以進行不同類型的指針轉換 該轉換較危險,很少使用,慎用
c++11的新特性
  • auto : auto可以根據上下文推測變量類型 auto聲明的變量必須要初始化.

    auto實際上實在編譯時對變量進行了類型推導,所以不會對程序的運行效率造成不良影響

  • nullptr:替換NULL,避免NULL可能導致的問題 NULL在C++中代表着0,而nullptr在任何時候都代表空指針。

  • 基於範圍的for循環:

    vector<int> v{1,2,3,4,5};
    for(const auto& e : v)
    	cout<<e<<endl;
    
  • 虛函數的override和final指示符

    • override,表示函數應當重寫基類中的虛函數
    • final,表示派生類不應當重寫這個虛函數
  • 智能指針:爲防止內存泄露等問題,用一個對象來管理野指針,使得在該對象構造時獲得該指針管理權,析構時自動釋放。包含在頭文件<memory>中

    智能指針名稱 細節
    auto_ptr 基於所有權轉移。 ( 已經被c++11拋棄)缺點:一個空間不能由兩個auto_ptr管理,不然會析構兩次;auto_ptr的拷貝構造會將原指針的管理權交給目標指針,會使得原指針懸空。故auto_ptr會導致一些內存泄漏和野指針問題
    unique_ptr “唯一”擁有其所指對象,保證同一時間內只有一個智能指針可以指向該對象。有效避免資源泄露(例如“以new創建對象後因爲發生異常而忘記調用delete”) 不共享它的指針,無法複製到其他unique_ptr(無拷貝構造函數),無法通過值傳遞到函數(無拷貝構造)
    shared_ptr 允許多個指針可以同時指向一個對象,當最後一個shared_ptr離開作用域時,內存纔會自動釋放。shared_ptr使用引用計數,每一個shared_ptr的拷貝都指向相同的內存。每使用他一次,內部的引用計數加1,每析構一次,內部的引用計數減1,減爲0時,自動刪除所指向的堆內存。注意避免循環引用,shared_ptr的一個最大的陷阱是循環引用(當兩個對象相互使用一個shared_ptr成員變量指向對方,會造成循環引用,使引用計數失效,從而導致內存泄漏)
    weak_ptr 不增加計數,爲了解決shared_ptr存在相互引用的問題,確保能夠正確析構。是一種不控制對象生命週期的智能指針, 它指向一個 shared_ptr 管理的對象。最大作用在於協助shared_ptr工作,像旁觀者那樣觀測資源的使用情況。weak_ptr可以從一個shared_ptr或者另一個weak_ptr對象構造,獲得資源的觀測權。但weak_ptr沒有共享資源,它的構造不會引起指針引用計數的增加。
  • STL

    容器名稱 細節
    unordered_map 採用HASH MAP實現(map內部實現了一個紅黑樹,故查找時間複雜度爲O(logn), unordered_map通過哈希映射實現查找複雜度爲O(1));如果沒有順序遍歷需求採用unordered_map通常更優
    unordered_set 採用HASH MAP實現(set採用紅黑樹實現)
    array 具有固定大小的數組。支持快速隨機訪問。不能添加或刪除元素。array除了有傳統數組支持隨機訪問、效率高、存儲大小固定等特點外,還支持迭代器訪問、獲取容量、獲得原始指針等高級功能
    forward_list 單向鏈表。forward_list和list的區別在於前者是單向鏈表,它的迭代器是前向有效的;後者是雙向鏈表,在內部存在兩個鏈接,它的迭代器是雙向有效的。
malloc/free 和new/delete
  • 相同點:都可用於申請動態內存和釋放內存
  • 區別:malloc只分配指定大小的堆內存空間,而new可以根據對象類型分配合適的堆內存空間。free釋放對應的堆內存空間,delete,先執行對象的析構函數,在釋放對象所佔空間。malloc分配時的大小是人爲計算的,返回類型是void*,使用時需要類型轉換,new在分配時,編譯器能夠根據對象類型自動計算出大小,返回類型是指向對象類型的指針。new調用構造函數構造對象,而malloc不能;delete將調用析構函數析構對象,而free不能
程序的內存分配
  • 棧區:由編譯器自動分配與釋放,存放爲運行時函數分配的局部變量、函數參數、返回數據、返回地址等
  • 堆區:一般由程序員分配釋放, 若程序員不釋放,程序結束時可能由OS回收
  • 全局區(靜態區static):存放全局變量、靜態數據、常量。程序結束後由系統釋放
  • 常量區(文字常量區):存放常量字符串,程序結束後有系統釋放
  • 代碼區:存放函數體(類成員函數和全局區)的二進制代碼
內存分配方式
  • 從靜態存儲區分配:內存在程序編譯的時候已經分配好,這塊內存在程序的整個運行期間都存在。例如全局變量,static變量。
  • 在棧上創建:在執行函數時,函數內局部變量的存儲單元可以在棧上創建,函數執行結束時,這些內存單元會自動被釋放。棧內存分配運算內置於處理器的指令集,效率高,但是分配的內存容量有限
  • 從堆上分配:程序在運行的時候使用malloc或者new申請任意多少的內存,程序員自己負責在何時用free或delete釋放內存。如果在堆上分配了空間,既有責任回收它,否則運行的程序會出現內存泄漏,頻繁的分配和釋放不同大小的堆空間將會產生內存碎片
C++類中數據成員初始化順序

1.成員變量在使用初始化列表初始化時,與構造函數中初始化成員列表的順序無關,只與定義成員變量的順序有關。

2.如果不使用初始化列表初始化,在構造函數內初始化時,此時與成員變量在構造函數中的位置有關。

3.類中const成員常量必須在構造函數初始化列表中初始化。

4.類中static成員變量,只能在類內外初始化(同一類的所有實例共享靜態成員變量)。

初始化順序:

  • 1) 基類的靜態變量或全局變量

  • 2) 派生類的靜態變量或全局變量

  • 3) 基類的成員變量

  • 4) 派生類的成員變量

虛函數的實現
  • 一個含有虛函數(無論是其本身的,還是繼承而來的)的類都至少有一個與之對應的虛函數表,其中存放着該類所有的虛函數對應的函數指針
  • 虛函數構造過程:
    • 先拷貝父類的虛函數表
    • 替換已重寫的虛函數指針
    • 增加自己再定義的虛函數指針
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章