面 C C 重難點總結系列(一) (五)

2021-09-11 08:15:28 字數 2723 閱讀 9779

c/c++重難點總結系列(一)

c/c++重難點總結系列(二)

c/c++重難點總結系列(三)

c/c++重難點總結系列(四)

重難點總結系列(五)

前言《c和指標》

《c陷阱與缺陷》

《c++ primer》 第五版

《effective c++》第三版

《深度探索c++物件模型》

持續更新中。。。

現更新到《c/c++重難點總結系列(五)》

1.關於程式的記憶體區域

(1)**區:存放程式的二進位制**。

(2)全域性區:存放全域性資料和靜態資料,編譯器編譯時即分配記憶體。全域性變數和靜態變數的儲存是放在一塊的。對於c語言初始化的全域性變數和靜態變數在一塊區域, 未初始化的全域性變數和未初始化的靜態變數在相鄰的另一塊區域。而c++則沒有這個區別,程式結束後由系統釋放。

(3)文字常量區 :常量字串就是放在這裡的。 程式結束後由系統釋放。

(5)堆:記憶體中開闢的另一塊區域,交給程式分配和釋放,故又稱動態記憶體。記憶體中堆的位址向高位址生長,若程式設計師分配的動態記憶體不及時釋放會導致記憶體洩露(執行時動態記憶體耗盡),程式結束時一般會由os** 。

2.關於函式的呼叫機制

(2)傳參機制:傳參不一定會壓棧!fastcall(快調)一般會由暫存器傳參,另外當引數不超過4個時一般也由暫存器傳參,否則會壓棧。壓棧順序一般從右到左。

3.關於三種傳參方式的比較

(1)值傳遞:其實是一種賦值操作,實參傳遞給形參時會產生額外的副本,形參只是實參的拷貝,所以函式內對形參的操作不會更新到源實參。在函式結束時,形參作為區域性變數會被釋放,對實參不會產生任何影響。若為類的物件會呼叫拷貝構造,這種深拷貝操作會影響到傳參效率。(可理解為「單向介面」)

(3)引用傳遞(c++特有):傳遞的是實參的別名,傳參時形參被繫結到實參物件上,因此函式內部對形參的操作也都會「同步更新」到源實參。(可理解為「雙向介面」)

注:關於指標傳遞和引用傳遞,形參改變對實參的改變是一種***,我們利用這種***可以方便修改傳遞的實參,另外,這種方式避免了值傳遞中的拷貝,對於大資料的實參可以有效提公升效率。因此,對於想提公升傳參效率又不想影響實參的情況,可以使用const:

bool isshorter(const string &s1,const string &s2)//const修飾指標傳參會有同樣的效果

{return s1.size()4.關於static用法

注:靜態區域性變數!=全域性變數,二者生命週期相同,但作用域不同,靜態區域性變數只對函式體內部可見。

(2)外部靜態變數/函式:

static修飾全域性變數:限定該變數只在該檔案中可用。

static修飾外部函式:往往在函式宣告中加static修飾,限定該函式只在該檔案可用(若在標頭檔案中宣告,則限定只在其對應的原始檔中可用)

(4)靜態成員變數/函式:類中static修飾的成員。靜態成員與類的物件實體無關,是該類的共享變數。

注:易錯點:靜態成員變數在類中static宣告後還需要在類外定義!否則編譯器報錯未定義。

5.關於extern

(1)extern修飾函式:c/c++標頭檔案中的函式宣告預設為extern,即外部可用(其他原始檔只需包含標頭檔案即可使用)。和static修飾的效果相反。

(2)extern修飾變數:帶extern的變數僅僅是宣告而不是定義!用extern使變數可以在多檔案中共享,主要有兩種做法:

a.在原始檔中定義,其他需要使用該變數的原始檔用extern宣告。(表示該變數在其它檔案中定義,即一次定義,多次extern宣告)

b.在原始檔中定義,其對應的標頭檔案中extern宣告,其他需要使用該變數的原始檔包含該標頭檔案即可。(更加標準的做法)

6.關於遞迴的安全性

遞迴過程其實是反覆壓棧、出棧的過程,遞迴進入時會壓棧,每遞迴一次,棧記憶體會多一截,遞迴逐級返回時即出棧。設想棧深度有限,而遞迴次數過多或無限遞迴時,必然導致棧溢位。

7.關於內聯

用途:定義或宣告函式時返回值前加上inline修飾能避免函式呼叫帶來的時間和空間開銷,提高效率,適用於反覆執行的核心**。內部實現機制其實是編譯時按函式體展開**,避免了函式呼叫的一系列壓棧出棧過程。

限制:(1)不能出現複雜的控制結構語句;

(2)遞迴函式不能用作內聯函式;

(3)內聯函式體不宜**過長,只適合數行的小函式。

注:1.內聯和巨集定義均屬於**替換機制,但前者安全性更好,巨集只是預處理做簡單的符號替換而不會做型別檢查。內聯可以完全替代巨集,反之不能。

2.inline關鍵字只是一種「建議」,是否採用內聯機制取決於編譯器。

8.關於過載

用途:c++特有機制。讓同一種演算法針對不同型別使用相同的函式名,提高**可讀性,過載的函式至少在引數個數或型別上有所區別,僅返回值區別不能過載!如:

void func(int);和int func(int);//編譯器無法區分

int abs(int);和double abs(double);//c++通過名字粉碎技術自動匹配

注:1.過載和重寫(覆蓋)是兩個完全不同的概念,重寫是物件導向中子類對父類虛函式的重新實現!各大網際網路公司筆試、面試常考題,然很多程式猿經常混為一談。

2.底層const修飾的引數以及常量成員函式也可以過載。

9.關於預設引數

用途:c++特有機制。函式宣告時加入預設值,呼叫時可忽略該引數直接使用預設值,提高編碼效率。預設值可以是常量、全域性變數、函式等。

限制:某個預設引數的後面所有引數均需要預設值,因此經常把帶有預設值的引數放在其他引數後面。

10.關於字元指標、字串常量和字元陣列名

C 重難點知識總結

c 提供了兩種指標運算子,一種是取位址運算子 一種是間接定址運算子 指標是乙個包含了另乙個變數位址的變數,可以把乙個包含了另乙個變數位址的變數說成是 指向 另乙個變數。變數可以是任意的資料型別,包括物件 結構或者指標。取位址運算子 是一元運算子,返回運算元的記憶體位址。例如,如果 var 是乙個整型...

ts重難點泛型總結

1.泛型 generics 定義返回任意型別的函式 function echo t arg t tconst res echo true function swapu tuple t u u,t const result2 swap string 123 result2 1 會彈出提示可以呼叫這裡面...

前端常用重難點總結之html篇

春節剛過,趁著有點空閒時間,總結了一些對我自身來說比較重要的前端重難點。精力所限就不一一展開了,首先發表html篇的重難點,後續會陸續發布css篇 js篇和vue篇 溫故而知新,可以為師矣。html篇 1 基礎 1 文件物件模型dom 乍看不重要其實是核心的東西 2 cookie 一般用於使用者登入...