C 細節問題

2021-07-05 15:47:42 字數 3739 閱讀 7306

參***

本質:引用是別名,指標是位址,具體的:

• 指標可以在執行時改變其所指向的值,引用一旦和某個物件繫結就不再改變

• 從記憶體上看,指標會分配記憶體區域,而引用不會,它僅僅是乙個別名

• 在引數傳遞時,引⽤用會做型別檢查,而指標不會

• 引用不能為空,指標可以為空

參***

本質:define只是字串替換,const參與編譯執行,具體的:

• define不會做型別檢查,const擁有型別,會執行相應的型別檢查

• define僅僅是巨集替換,不佔⽤用記憶體,⽽而const會占用記憶體

• const記憶體效率更高,編譯器通常將const變數儲存在符號表中,而不會分配儲存空間,這使得它成 為乙個編譯期間的常量,沒有儲存和讀取的操作

參***

本質:define只是字串替換,inline由編譯器控制,具體的:

• define只是簡單的巨集替換,通常會產生二義性;而inline會真正地編譯到**中

• inline函式是否展開由編譯器決定,有時候當函式太大時,編譯器可能選擇不展開相應的函式

參***

1,malloc與free是c++/c語言的標準庫函式,new/delete是c++的運算子。它們都可用於申請動態記憶體和釋放記憶體。

2,對於非內部資料型別的物件而言,光用maloc/free無法滿足動態物件的要求。物件在建立的同時要自動執行建構函式,物件在消亡之前要自動執行析構函式。由於malloc/free是庫函式而不是運算子,不在編譯器控制許可權之內,不能夠把執行建構函式和析構函式的任務強加於malloc/free。

3,因此c++語言需要乙個能完成動態記憶體分配和初始化工作的運算子new,以乙個能完成清理與釋放記憶體工作的運算子delete。注意new/delete不是庫函式。

4,c++程式經常要呼叫c函式,而c程式只能用malloc/free管理動態記憶體。

5、new可以認為是malloc加建構函式的執行。new出來的指標是直接帶型別資訊的。而malloc返回的都是void指標。

參***

1、隱藏:當同時編譯多個檔案時,所有未加static字首的全域性變數和函式都具有全域性可見性。

static可以用作函式和變數的字首,對於函式來講,static的作用僅限於隱藏.

2、static的第二個作用是保持變數內容的持久:儲存在靜態資料區的變數會在程式剛開始執行時就完成初始化,也是唯一的一次初始化。

共有兩種變數儲存在靜態儲存區:全域性變數和static變數,只不過和全域性變數比起來,static可以控制變數的可見範圍,

說到底static還是用來隱藏的。雖然這種用法不常見

3、static的第三個作用是預設初始化為0(static變數)

4、c++中的作用

1)不能將靜態成員函式定義為虛函式。

2)靜態資料成員是靜態儲存的,所以必須對它進行初始化。 (程式設計師手動初始化,否則編譯時一般不會報錯,但是在link時會報錯誤)

3)靜態資料成員在《定義或說明》時前面加關鍵字static。

【解答】

static關鍵字至少有下列n個作用:

(1)函式體內static變數的作用範圍為該函式體,不同於auto變數,該變數的記憶體只被分配一次,因此其值在下次呼叫時仍維持上次的值;

(2)在模組內的static全域性變數可以被模組內所用函式訪問,但不能被模組外其它函式訪問;

(3)在模組內的static函式只可被這一模組內的其它函式呼叫,這個函式的使用範圍被限制在宣告它的模組內;

(4)在類中的static成員變數屬於整個類所擁有,對類的所有物件只有乙份拷貝;

(5)在類中的static成員函式屬於整個類所擁有,這個函式不接收this指標,因而只能訪問類的static成員變數。

const關鍵字至少有下列n個作用:

(1)欲阻止乙個變數被改變,可以使用const關鍵字。在定義該const變數時,通常需要對它進行初始化,因為以後就沒有機會再去改變它了;

(2)對指標來說,可以指定指標本身為const,也可以指定指標所指的資料為const,或二者同時指定為const;

(3)在乙個函式宣告中,const可以修飾形參,表明它是乙個輸入引數,在函式內部不能改變其值;

(4)對於類的成員函式,若指定其為const型別,則表明其是乙個常函式,不能修改類的成員變數;

(5)對於類的成員函式,有時候必須指定其返回值為const型別,以使得其返回值不為「左值」。例如:

const classa operator*(const classa& a1,const classa& a2);

operator*的返回結果必須是乙個const物件。如果不是,這樣的****也不會編譯出錯:

classa a, b, c;

(a * b) = c; // 對a*b的結果賦值

操作(a * b) = c顯然不符合程式設計者的初衷,也沒有任何意義。

參***

• reinterpret_cast: 轉換乙個指標為其它型別的指標。它也允許從乙個指標轉換為整數型別,反之亦 然. 這個操作符能夠在非相關的型別之間轉換. 操作結果只是簡單的從乙個指標到別的指標的值的 二進位制拷貝. 在型別之間指向的內容不做任何型別的檢查和轉換?

class a{};

class b{};

a* a = new a;

b* b = reinterpret_cast(a);

• static_cast: 允許執行任意的隱式轉換和相反轉換動作(即使它是不允許隱式的),例如:應用到類 的指標上, 意思是說它允許子類型別的指標轉換為父類型別的指標(這是乙個有效的隱式轉換), 同 時, 也能夠執行相反動作: 轉換父類為它的子類

class base {};

class derive:public base{};

base* a = new base;

derive *b = static_cast(a);

• dynamic_cast: 只用於物件的指標和引用. 當用於多型型別時,它允許任意的隱式型別轉換以及相 反過程. 不過,與static_cast不同,在後一種情況裡(注:即隱式轉換的相反過程),dynamic_cast 會檢查操作是否有效. 也就是說, 它會檢查轉換是否會返回乙個被請求的有效的完整物件。檢測在 執行時進行. 如果被轉換的指標不是乙個被請求的有效完整的物件指標,返回值為null. 對於引用 型別,會丟擲bad_cast異常

• const_cast: 這個轉換型別操縱傳遞物件的const屬性,或者是設定或者是移除,例如:

class c{};

const c* a = new c;

c *b = const_cast(a);

參***

要點是要答出虛函式表和虛函式表指標的作用。c++中虛函式使用虛函式表和 虛函式表指標實現,虛函式表是乙個類的虛函式的位址表,用於索引類本身以及父類的虛函式的地 址,假如子類的虛函式重寫了父類的虛函式,則對應在虛函式表中會把對應的虛函式替換為子類的 虛函式的位址;虛函式表指標存在於每個物件中(通常出於效率考慮,會放在物件的開始位址處), 它指向物件所在類的虛函式表的位址;在多繼承環境下,會存在多個虛函式表指標,分別指向對應 不同基類的虛函式表。

參***

可以,但是沒有動態繫結的效果,父類建構函式中呼叫的仍然是父類版本的函式,子類中呼叫的仍然是子類版本的函式

參***

虛繼承用於解決多繼承條件下的菱形繼承問題,底層實現原理與編譯器相關,一般通過虛基類 指標實現,即各物件中只儲存乙份父類的物件,多繼承時通過虛基類指標引用該公共物件,從而避 免菱形繼承中的二義性問題。

參考**:

C 細節問題

都是語言,為什麼英語比c 難這麼多呢?chapter 1 chapter 2 chapter 3 chapter 4 程式設計基礎 物件導向基礎 標準模板庫 編譯及除錯 c c 的內容又多又雜,常常看到有人羅列相關書單,覺得毫無意義,我不相信他們真的完全掌握了其中任何一本。學習任何東西,首先要掌握基...

專案問題細節

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

synchronized細節問題

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