C 面試常見問題

2021-10-09 01:56:07 字數 4444 閱讀 3806

智慧型指標的作用是管理乙個指標,因為存在以下這種情況:申請的空間在函式結束時忘記釋放,造成記憶體洩漏。使用智慧型指標可以很大程度上的避免這個問題,因為智慧型指標就是乙個類,當超出了類的作用域是,類會自動呼叫析構函式,析構函式會自動釋放資源。所以智慧型指標的作用原理就是在函式結束時自動釋放記憶體空間,不需要手動釋放記憶體空間。

auto_ptr(c++98的方案,cpp11已經拋棄)

採用所有權模式。

auto_ptr< string> p1 (

new string ("i reigned lonely as a cloud.」));

auto_ptr p2;

p2 = p1;

//auto_ptr不會報錯.

此時不會報錯,p2剝奪了p1的所有權,但是當程式執行時訪問p1將會報錯。所以auto_ptr的缺點是:存在潛在的記憶體崩潰問題

unique_ptr:實現獨佔式擁有或嚴格擁有概念,保證同一時間內只有乙個智慧型指標可以指向該物件。它對於避免資源洩露(例如「以new建立物件後因為發生異常而忘記呼叫delete」)特別有用。當程式試圖將乙個 unique_ptr 賦值給另乙個時,如果源 unique_ptr 是個臨時右值,編譯器允許這麼做;如果源 unique_ptr 將存在一段時間,編譯器將禁止這麼做,比如:

unique_ptr

pu1(

new string (

"hello world"))

;unique_ptr pu2;

pu2 = pu1;

// #1 not allowed

unique_ptr pu3;

pu3 = unique_ptr

(new string (

"you"))

;// #2 allowed

如果確實想執行類似與#1的操作,要安全的重用這種指標,可給它賦新值。c++有乙個標準庫函式std::move(),讓你能夠將乙個unique_ptr賦給另乙個:

unique_ptr ps1, ps2;

ps1 =

demo

("hello");

ps2 =

move

(ps1)

;ps1 =

demo

("alexia");

cout <<

*ps2 <<

*ps1 << endl;

shared_ptr: 實現共享式擁有概念。多個智慧型指標可以指向相同物件,該物件和其相關資源會在「最後乙個引用被銷毀」時候釋放。從名字share就可以看出了資源可以被多個指標共享,它使用計數機制來表明資源被幾個指標共享。可以通過成員函式use_count()來檢視資源的所有者個數。除了可以通過new來構造,還可以通過傳入auto_ptr, unique_ptr,weak_ptr來構造。當我們呼叫release()時,當前指標會釋放資源所有權,計數減一。當計數等於0時,資源會被釋放。

shared_ptr 是為了解決 auto_ptr 在物件所有權上的侷限性(auto_ptr 是獨佔的), 在使用引用計數的機制上提供了可以共享所有權的智慧型指標。

成員函式:

use_count 返回引用計數的個數

unique 返回是否是獨佔所有權( use_count 為 1)

swap 交換兩個 shared_ptr 物件(即交換所擁有的物件)

reset 放棄內部物件的所有權或擁有物件的變更, 會引起原有物件的引用計數的減少

get 返回內部物件(指標), 由於已經過載了()方法, 因此和直接使用物件是一樣的.如 shared_ptr sp(new int(1)); sp 與 sp.get()是等價的

weak_ptr: 是一種不控制物件生命週期的智慧型指標,它指向乙個 shared_ptr 管理的物件. 進行該物件的記憶體管理的是那個強引用的 shared_ptr. weak_ptr只是提供了對管理物件的乙個訪問手段。weak_ptr 設計的目的是為配合 shared_ptr 而引入的一種智慧型指標來協助 shared_ptr 工作, 它只可以從乙個 shared_ptr 或另乙個 weak_ptr 物件構造, 它的構造和析構不會引起引用記數的增加或減少。weak_ptr是用來解決shared_ptr相互引用時的死鎖問題,如果說兩個shared_ptr相互引用,那麼這兩個指標的引用計數永遠不可能下降為0,資源永遠不會釋放。它是對物件的一種弱引用,不會增加物件的引用計數,和shared_ptr之間可以相互轉化,shared_ptr可以直接賦值給它,它可以通過呼叫lock函式來獲得shared_ptr。

classb;

classa}

;classb}

;void

fun(

)int

main()

可以看到fun函式中pa ,pb之間互相引用,兩個資源的引用計數為2,當要跳出函式時,智慧型指標pa,pb析構時兩個資源引用計數會減一,但是兩者引用計數還是為1,導致跳出函式時資源沒有被釋放(a b的析構函式沒有被呼叫),如果把其中乙個改為weak_ptr就可以了,我們把類a裡面的shared_ptr pb_; 改為weak_ptr pb_; 執行結果如下,這樣的話,資源b的引用開始就只有1,當pb析構時,b的計數變為0,b得到釋放,b釋放的同時也會使a的計數減一,同時pa析構時使a的計數減一,那麼a的計數為0,a得到釋放。

注意的是我們不能通過weak_ptr直接訪問物件的方法,比如b物件中有乙個方法print(),我們不能這樣訪問,pa->pb_->print(); 英文pb_是乙個weak_ptr,應該先把它轉化為shared_ptr,如:shared_ptr p = pa->pb_.lock(); p->print();

模板定義:模板就是實現**重用機制的一種工具,它可以實現型別引數化,即把型別定義為引數, 從而實現了真正的**可重用性。模版可以分為兩類,乙個是函式模版,另外乙個是類模版。

1.阻塞io:呼叫者呼叫了某個函式,等待這個函式返回,期間什麼也不做,不停的去檢查這個函式有沒有返回,必須等這個函式返回才能進行下一步動作

2.非阻塞io:非阻塞等待,每隔一段時間就去檢測io事件是否就緒。沒有就緒就可以做其他事。

3.訊號驅動io:訊號驅動io:linux用套介面進行訊號驅動io,安裝乙個訊號處理函式,程序繼續執行並不阻塞,當io時間就緒,程序收到sigio訊號。然後處理io事件。

4.io復用:多路轉接io:linux用select/poll函式實現io復用模型,這兩個函式也會使程序阻塞,但是和阻塞io所不同的是這兩個函式可以同時阻塞多個io操作。而且可以同時對多個讀操作、寫操作的io函式進行檢測。知道有資料可讀或可寫時,才真正呼叫io操作函式

5.非同步io:linux中,可以呼叫aio_read函式告訴核心描述字緩衝區指標和緩衝區的大小、檔案偏移及通知的方式,然後立即返回,當核心將資料拷貝到緩衝區後,再通知應用程式。

程序對應的記憶體空間中所包含的5種不同的資料區:

**段:**段是用來存放可執行檔案的操作指令,也就是說是它是可執行程式在記憶體中的映象。**段需要防止在執行時被非法修改,所以只准許讀取操作,而不允許寫入(修改)操作——它是不可寫的

資料段:資料段用來存放可執行檔案中已初始化全域性變數,換句話說就是存放程式靜態分配的變數和全域性變數

bss段:bss段包含了程式中未初始化的全域性變數,在記憶體中 bss段全部置零

:堆是用於存放程序執行中被動態分配的記憶體段,它的大小並不固定,可動態擴張或縮減。當程序呼叫new、malloc等函式分配記憶體時,新分配的記憶體就被動態新增到堆上(堆被擴張);當利用free等函式釋放記憶體時,被釋放的記憶體從堆中被剔除(堆被縮減)

:棧是使用者存放程式臨時建立的區域性變數,也就是說我們函式括弧「{}」中定義的變數(但不包括static宣告的變數,static意味著在資料段中存放變數)。除此以外,在函式被呼叫時,其引數也會被壓入發起呼叫的程序棧中,並且待到呼叫結束後,函式的返回值也會被存放回棧中。由於棧的先進先出特點,所以棧特別方便用來儲存/恢復呼叫現場。從這個意義上講,我們可以把堆疊看成乙個寄存、交換臨時資料的記憶體區。

邏輯位址 -->(分段機制) 線性位址 -->(分頁機制) 實體地址。在linux下,邏輯位址與線性位址總是一致,即邏輯位址的偏移量欄位的值與線性位址的值總是相同的

段式管理——邏輯位址轉線性位址

邏輯位址由兩部份組成,【段識別符號:段內偏移量】

段起始位址+ 段內偏移量 = 線性位址

頁式管理——線性位址轉實體地址

C 面試常見問題

1.引用和指標的區別 區別 1 引用不能為空,指標可以為空 2 引用必須初始化,指標不需要 3 引用初始化以後不能改變,指標可以改變初始化物件後的值 4 引用訪問物件後是直接訪問,指標訪問物件是間接訪問 5 引用大小是所引用物件的大小,指標大小是指標類本身的大小 6 引用沒有const,指標有con...

C 面試常見問題(五)

使用動態庫進行鏈結。動態庫 so dll 具體的區別下面這篇部落格講得比較詳細。大家可以移步至 c 靜態庫與動態庫 因此乙個物件的大小 所有非靜態成員大小的總和 由以上分析可以得到菱形繼承物件的記憶體大小問題 includeusing namespace std class a 大小為8,int 4...

C 面試常見問題補充

c 面試常見問題 1.指標常量 int const p 和常量指標的區別 const int p int const p 指標常量 本質上是乙個常量,指標用來說明常量的型別,表示該常量是乙個指標型別的常量。在指標常量中,指標自身的值是乙個常量,不可改變,始終指向同乙個位址,在定義的同時必須初始化。指...