C 細節問題

2022-09-17 04:36:08 字數 4443 閱讀 6573

都是語言,為什麼英語比c++難這麼多呢?

chapter 1

chapter 2

chapter 3

chapter 4

程式設計基礎

物件導向基礎

標準模板庫

編譯及除錯

c/c++的內容又多又雜,常常看到有人羅列相關書單,覺得毫無意義,我不相信他們真的完全掌握了其中任何一本。學習任何東西,首先要掌握基本概念,基礎不牢地動山搖,因為高階的內容都是通過低階的概念來描述的。當基本概念都沒理解透,學習再多都是空中樓閣。這裡羅列了一些聽基本的問題,雖然看著不難,但是精確理解每句話中的每個詞真的並不容易。

變數宣告和定義區別?

"零值比較"?

strlen和sizeof區別?

同一不同物件可以互相賦值嗎?

結構體內存對齊問題?

static作用是什麼?在c和c++中有何區別?

結構體和類的區別?

- 結構體不可以繼承,類可以。 c++中結構體也可以繼承。

malloc和new的區別?

指標和引用區別?

- 引用只是別名,不占用具體儲存空間,只有宣告沒有定義;指標是具體變數,需要占用儲存空間。

巨集定義和函式有何區別?

巨集定義和const區別?

巨集定義和typedef區別?

巨集定義和內聯函式(inline)區別?

條件編譯#ifdef, #else, #endif作用?

區別以下幾種變數?

const int a;

int const a;

const int *a;

int *const a;

volatile有什麼作用?

什麼是常引用?

區別以下指標型別?

int *p[10]

int (*p)[10]

int *p(int)

int (*p)(int)

常量指標和指標常量區別?

a和&a有什麼區別?

假設陣列int a[10];

int (*p)[10] = &a;

陣列名和指標(這裡為指向陣列首元素的指標)區別?

野指標是什麼?

堆和棧的區別?

申請大小限制不同。

申請效率不同。

delete和delete區別?

能夠準確理解下面這些問題是從c程式設計師向c++程式設計師高階的基礎。當然了,這只是一部分。

物件導向三大特性?

public/protected/private的區別?

物件儲存空間?

c++空類有哪些成員函式?

建構函式能否為虛函式,析構函式呢?

建構函式:

構造函式呼叫順序,析構函式呢?

拷貝建構函式中深拷貝和淺拷貝區別?

拷貝建構函式和賦值運算子過載的區別?

注:類中有指標變數時要重寫析構函式、拷貝建構函式和賦值運算子

虛函式和純虛函式區別?

覆蓋、過載和隱藏的區別?

在main執行之前執行的**可能是什麼?

哪幾種情況必須用到初始化成員列表?

什麼是虛指標?

過載和函式模板的區別?

this指標是什麼?

類模板是什麼?

建構函式和析構函式呼叫時機?

stl內容雖然看起來很多,單獨成書都不是問題(《stl原始碼剖析》),但從實際使用狀況來看,我認為只需要知道以下幾點就可以了:

string

vector

用法:

定義:

vectorvec;

插入元素:

vec.push_back(element);

vec.insert(iterator, element);

刪除元素:

vec.pop_back();

vec.erase(iterator);

修改元素:

vec[position] = element;

遍歷容器:

for(auto it = vec.begin(); it != vec.end(); ++it)

其他:vec.empty(); //判斷是否空

vec.size(); // 實際元素

vec.capacity(); // 容器容量

vec.begin(); // 獲得首迭代器

vec.end(); // 獲得尾迭代器

vec.clear(); // 清空

實現:

模擬vector實現

需要連續的物理儲存空間。

每當大小不夠時,重新分配記憶體(*2),並複製原內容。

錯誤避免:

迭代器失效

刪除元素

map

用法:

定義:

mapmymap;

插入元素:

mymap.insert(pair(key, value)); // 同key不插入

mymap.insert(map::value_type(key, value)); // 同key不插入

mymap[key] = value; // 同key覆蓋

刪除元素:

mymap.erase(key); // 按值刪

mymap.erase(iterator); // 按迭代器刪

修改元素:

mymap[key] = new_value;

遍歷容器:

for(auto it = mymap.begin(); it != mymap.end(); ++it)

實現:

rbtree實現

rbtree本身也是二叉排序樹的一種,key值有序,且唯一。

基於紅黑樹實現的map結構(實際上是map, set, multimap,multiset底層均是紅黑樹),不僅增刪資料時不需要移動資料,其所有操作都可以在o(logn)時間範圍內完成。另外,基於紅黑樹的map在通過迭代器遍歷時,得到的是key按序排列後的結果,這點特性在很多操作中非常方便。

面試時候現場寫紅黑樹**的概率幾乎為0,但是紅黑樹一些基本概念還是需要掌握的。

它是二叉排序樹(繼承二叉排序樹特顯):

它滿足如下幾點要求:

查詢時間一定可以控制在o(logn)。

紅黑樹的節點定義如下:

enum color ;

struct rbtreenode ;

所以對紅黑樹的操作需要滿足兩點:1.滿足二叉排序樹的要求;2.滿足紅黑樹自身要求。通常在找到節點通過和根節點比較找到插入位置之後,還需要結合紅黑樹自身限制條件對子樹進行左旋和右旋。

相比於**l樹,紅黑樹平衡性要稍微差一些,不過建立紅黑樹時所需的旋轉操作也會少很多。相比於最簡單的bst,bst最差情況下查詢的時間複雜度會上公升至o(n),而紅黑樹最壞情況下查詢效率依舊是o(logn)。所以說紅黑樹之所以能夠在stl及linux核心中被廣泛應用就是因為其折中了兩種方案,既減少了樹高,又減少了建樹時旋轉的次數。

從紅黑樹的定義來看,紅黑樹從根到null的每條路徑擁有相同的黑節點數(假設為n),所以最短的路徑長度為n(全為黑節點情況)。因為紅節點不能連續出現,所以路徑最長的情況就是插入最多的紅色節點,在黑節點數一致的情況下,最可觀的情況就是黑紅黑紅排列......最長路徑不會大於2n,這裡路徑長就是樹高。

set

編譯

預處理編譯

鏈結各個源**模組獨立的被編譯,然後將他們組裝起來成為乙個整體,組裝的過程就是鏈結。被鏈結的各個部分本本身就是二進位制檔案,所以在被鏈結時需要將所有目標檔案的**段拼接在一起,然後將所有對符號位址的引用加以修正。

如果僅僅像上面的步驟是沒有辦法正常使用庫的,我們可以通過加-lpath指定搜尋庫檔案的目錄(-l.表示當前目錄),預設情況下會到環境變數ld_library_path指定的目錄下搜尋庫檔案,預設情況是/usr/lib,我們可以將庫檔案拷貝到那個目錄下再鏈結。

比較靜態庫和動態庫我們可以得到二者的優缺點。

動態庫另乙個有點就是更新很容易,當庫發生變化時,如果介面沒變只需要用新的動態庫替換掉就可以了。但是如果是靜態庫的話就需要重新被編譯。

不過靜態庫也有優點,主要就是靜態庫一次性完成了所有內容的繫結,執行時就不必再去考慮鏈結的問題了,執行效率會稍微高一些。

makefile編寫

對於大的工程通常涉及很多標頭檔案和原始檔,編譯起來很很麻煩,makefile正是為了自動化編譯產生的,makefile像是編譯說明書,指示編譯的步驟和條件,之後被make命令解釋。

鏈結

符號解析

重定位可執行目標檔案

載入

C 細節問題

參 本質 引用是別名,指標是位址,具體的 指標可以在執行時改變其所指向的值,引用一旦和某個物件繫結就不再改變 從記憶體上看,指標會分配記憶體區域,而引用不會,它僅僅是乙個別名 在引數傳遞時,引 用會做型別檢查,而指標不會 引用不能為空,指標可以為空 參 本質 define只是字串替換,const參與...

專案問題細節

最近專案很有問題,關於客戶需求,我們表現出來的就是很沒有經驗,很不專業。1.客戶要求的急,需要24小時不停的解決,但是由於人數有限,不可能不讓人睡覺,在這種高度緊張的條件下,發布的版本的質量也可想而知。2.客戶發現乙個問題就出版本,然後測試,又發現了新的問題,又出版本,這樣頻繁的折騰,最後只會像電腦...

synchronized細節問題

一 synchronized有鎖重入的特點,某個執行緒得到物件的鎖後,再次請求此物件可以再次得到改物件的鎖。如下示例,在method1中呼叫method2,在method2中呼叫method3,而method1 method2和method3都是加了synchronized關鍵字的。public c...