c 基礎知識回顧

2022-03-13 16:22:35 字數 4258 閱讀 5075

1.資料型別和類。

所有程式設計都是處理輸入和輸出。

關於輸入引數,從右至左把引數入棧,這樣根據棧基址,可以定位第乙個引數。因為很多函式是引數數量不定的,比如printf.

關於輸出,記得輸出時,一般是把值放入eax 暫存器,

所以一般資料型別,直接放入返回值資料,暫存器可以裝下,

而返回物件,會返回物件的指標,並在呼叫者的棧中,按位複製。之後清棧

而返回指標,會把指標放入暫存器,之後清棧。

隱藏守則:如果是返回乙個集合,如vector<>,而裡面是指標,就相當於返回了區域性物件的指標。

所以最佳實踐:

函式中:

物件的建立,必須明確,僅僅是區域性使用,還是會傳出去,區域性使用,就可以直接在棧中,如果會傳出去(或返回,或包含在返回物件中,或作為引數),必須傳遞物件,或者堆中的位址(智慧型指標)

就算是主函式中,不會清棧的情況下。還是為了語義的正確和統一性已經效能,也必須在堆中申請。

類中:

如果是類中的變數,自己new 了,必須自己delete .如果是指標,由外部傳入,那麼必須使用智慧型指標(因為你不確定使用者何時會delete)

一句話,除考慮效能之外,判斷是否new,看變數的生存期是本函式,還是超過本函式。

考慮效能,可以對於生存期在本函式類的變數。new 之後再 delete.極端情況是個大資料,而中間還要呼叫很深的棧。

非常明確的區域性使用小物件,小資料,不需要new.否則智慧型指標吧。

當然根據 raii,用類管理資源的守則,應該寫成用類管理資源。

但是預設的複製建構函式是按位複製。所以會出現2次析構。導致錯誤。

所以1,自定義複製建構函式。

2,使用智慧型指標。

使用智慧型指標,就為我們定義了乙個根據引數進行的析構函式,只有當引數為0才進行delete 操作。

使用智慧型指標,就要說到為什麼使用指標。必須要使用指標的場合,自己好像只碰到過的,只有在繼承場合下。而且此指標需要傳遞給外部。否則可以區域性物件,加&。

所以準則2:當由於繼承或其他情況下需要使用指標時,使用智慧型指標代替原指標。用智慧型指標這個模板類來管理資源。

再返回去說資料。基本資料沒什麼好說。int,char,都是定死的資源。對於c來說。使用指標感覺就是為了char *.字串。

類,只包含基本型別。也沒什麼好說。複製是成員資料型別按位複製,

如果類包含另外乙個類的物件。那麼1,為了節省棧空間。可以只包含類的指標。2,同乙個物件會被不同的類包含,那麼必須使用指標就節省了整個記憶體。

使用指標,當然就是用智慧型指標,省去自己處理拷貝建構函式的編寫。

根據準則一,不要返回區域性變數的指標,我們可以返回區域性變數,而繼承必須使用指標來表示。所以有一種必須使用new  的場合,就是返回包含派生類指標的集合。

所以目前總結,適合使用到智慧型指標(指標)的場合:1.繼承,2。某個類的物件,會被多個另外不同的物件包含。3.需要作為返回值,而為了效能,可以返回堆中的位址(智慧型指標)4.容器包含指標,而且作為返回值,必須在堆中new.

所以準則3:

不考慮效能問題,必須使用new,就1種情況,需要返回派生類指標的集合,如 vectorfun (); 那麼必須在函式中用new;

考慮效能,使用new,多3種情況。1.返回智慧型指標,而不是類物件。2.某個類的物件,會被另外類的多個不同的物件包含,那麼復合類,採用智慧型指標,3某個類的成員是個大資料,比如快取類,必須使用new到堆中,棧放不下。以免使用者,直接

在棧中生成物件。

而使用指標在上面的情況外。就是繼承。

2.再談輸入與輸出。

所以綜合考慮,寫函式。除非效能和棧空間的考慮,基本可以不用到new .除非需要返回派生類指標的集合

而使用指標也很有限。1.就是為了多型,使用指標。2.傳遞指標給函式,函式需要修改資料。

3構造和析構

如上所訴,類中需要使用智慧型指標成員,就是1,為了多型。2為了效能。

感覺不如用function.

建構函式中不能呼叫基類的虛構造。

析構函式不讓異常逃出。

基類必須實現虛析構。

5.資源管理

6.一般實踐:

函式內部變數:

1.非常明確的區域性變數(不返回,不作為引數)的小資料,用物件,不需要new.

2.否則智慧型指標吧。

函式引數和返回值:

1.不需要修改那麼const ref

2.如要修改用原始指標

3.返回必定智慧型指標(google 的硬性規定就是指標,好像不推薦返回物件)

見例子,非常實用的乾貨。

class request : boost::noncopyable ;

class buffer ;

//return unique_ptr means caller taking ownership

std::unique_ptrparserequest(buffer*inputmessage)

//pass unique_ptr means callee taking ownership

void processrequest(std::unique_ptrreq)

//pass raw pointer means changing it but not taking ownership

void augmentrequest(request*req)

//pass const reference means read it but not taking ownership

bool validaterequest(const request&req)

void onnetworkmessage(buffer*inputmessage)

}類內部變數:

以下3種情況有智慧型指標,或者引用。否則直接物件。

1)多型必須指標,就智慧型指標

2)可能和別的類共享,或者只是引用某個物件,所以生命週期不是很確定(考慮智慧型指標)

就比如lock_gurad ,鎖類,裡面的互斥鎖mutex ,必須是外部物件引用(stl裡面放入的是引用)。 智慧型鎖類,不管理鎖本身記憶體,只關注鎖的鎖定和放鎖。

#include #include 

"stdio.h

"#include

#include

#include

#include

#include

#include

#include

using

namespace

std;

mutex mtx;

class

mylock_guard

~mylock_guard()

private

: mylock_guard(

const mylock_guard&);

mylock_guard& operator=(const mylock_guard&);

mutex&mtx;

};void

showmsg()

intmain()

3)大資料,如果定義成物件,會導致當前物件無法在棧內建立

C語言基礎知識回顧

逗號運算 scanf和printf輸入 輸出 迴圈 switch break和continue的區別 主函式是乙個程式的入口,整個程式開始執行的位置,乙個程式中最多只能有乙個主函式,也可以沒有。int main void 運算子 含義語法 返回值 與a b ab都真,則真 其他為假 或 a b ab...

關於C 基礎知識回顧

使用反射呼叫方法 一旦知道乙個型別所支援的方法,就可以對方法進行呼叫。呼叫時,需使用包含在 methodinfo中的invoke 方法。呼叫形式 object invoke object ob,object args 這裡ob是乙個物件引用,將呼叫它所指向的物件上的方法。對於靜態方法,ob必須為nu...

MySQL知識回顧 MySQL基礎知識回顧

markdownpad document mysql mysql 是用於管理檔案的乙個軟體 服務端軟體 socket服務端 本地檔案操作 解析指令 sql語句 客戶端軟體 各種各樣 socket客戶端 傳送指令 解析指令 sql語句 ps dbms 資料庫管理系統 sql語句 需要掌握的技能 安裝 ...