C 和 C++的區別 / struct 和 class 的區別 / 指針和引用的區別 / new 與 malloc 的區別 / 堆和棧的區別 / sizeof 和 strlen 的區別

C 和 C++ 的區別

主要從以下三個方面來談:

  • 設計思想、編程思想方面
  • 語言特性方面(語法、內存管理、庫)
  • 執行效率方面

C 是面向過程的語言,而 C++ 是面向對象的語言,因此 C++ 語言中有類和對象以及繼承多態這樣的面嚮對象語言必備的內容,此外 C++ 支持模板,運算符重載,異常處理機制,以及一個非常強大的 C++ 標準模板庫 STL,另外一個 Boost 庫現在也歸屬 C++ 標準庫,提供了很多強大的功能。

C 只能寫面向過程的代碼,而 C++ 既可以寫面向過程的代碼,也可以實現面向對象的代碼;C++ 有許多設計模式,比如單例、工廠、觀察者模式等等,這些在 C 語言當中都是不支持的。由於 C++ 是面向對象的語言,支持類對象,類和類之間組合,繼承,多態等等面向對象的設計,有很多的設計模式可以直接使用,因此在設計大型軟件的時候,通常都會採用面嚮對象語言,而不會採用面向過程語言,可以更好的進行模塊化設計,做到軟件設計的準則:高內聚、低耦合!

內存管理上了,C 語言通過 malloc 和 free 來進行堆內存的分配和釋放,而 C++ 是通過 new 和 delete 來管理堆內存的。

強制類型轉換上也不一樣,C 的強制類型轉換使用小括號裏面加類型進行類型強轉的,而 C++ 有四種自己的類型強轉方式,分別是 const_cast、static_cast、reinterpret_cast 和 dynamic_cast。

輸入輸出方式也不一樣,C語言是用printf/scanf,他們是 C 的庫函數, C++ 是用cout/cin ,是 ostream 和 istream 類型的對象。

C++ 支持帶有默認值的函數、函數的重載、inline 內聯函數,C 語言都不支持。

由於 C++ 多了一個類,因此和 C 語言的作用域比起來,就多了一個類作用域,C++ 還支持命名空間,可以讓用戶自己定義新的命名空間,避免全局的名字衝突問題。

C++ 不僅支持指針,還支持引用,引用比指針更安全。但在彙編代碼上,指針和引用的操作是一樣的,而且在底層引用也是通過指針來實現的。

C++ 中 struct 和 class 的區別
C++ 中對 struct 的功能進行了很多的擴充,它可以有自己的成員函數、構造函數,也可以實現繼承、多態,class 可以繼承 struct、struct 可以繼承 class。

它們的區別在於三點:

  • 默認的成員變量訪問權限
    struct 對數據成員的默認訪問權限是 public 的,class 默認是 private 的。
  • 默認的繼承訪問權限
    struct 的默認繼承權限是 public 的,class 默認是 private 的。
  • class 可以定義模板參數,但 struct 不可以。

指針和引用的區別

  • 指針是一個實體,它是一個地址,指向一塊內存區域;引用是一個別名,並不是一個實體。
  • 底層指針和引用的實現是一樣的,它們的效率是一致的,具體在於編譯器的處理不同。
  • 編譯時期生成符號表,存儲變量名和變量地址,對於指針來說,符號表中存儲指針名和指針本身的地址;指針在運行時可以改變其值或者指向。對於引用來說,符號表中存儲引用對象的地址,符號表一旦生成,程序運行過程中不會修改,因此引用初始化後不可改變(其所引用的對象可以改變)。
  • 內存分配方面:程序爲指針是分配內存的,而對於引用是不分配內存的,因此存在多級指針,但只有一級引用。
  • 大小方面:對一個指針使用 sizeof,返回的是指針變量本身的大小,4 或 8 字節,但是對一個引用使用 sizeof,返回的是其引用的對象的大小。
  • 作爲函數形參:引用做函數形參,那麼在函數內部,對形參的修改即爲對實參的修改。指針做函數形參,若是對指針本身做操作,不會影響實參指針,因爲形參指針是實參指針的副本,但是對其所指向的內容操作,會更改實參所指的內容。
  • 自增運算:對指針做自增運算會只指向下一個地址,而對引用做自增運算會使所指對象自增。

new 與 malloc 的區別

  • new 操作符從自由存儲區(free store)上爲對象動態分配內存空間,而 malloc 函數從堆上動態分配內存。
  • new 操作符內存分配成功時,返回的是對象類型的指針,類型嚴格與對象匹配,無須進行類型轉換,故 new 是符合類型安全性的操作符。而 malloc 內存分配成功則是返回 void*,需要通過強制類型轉換將 void* 指針轉換成我們需要的類型。
  • new 內存分配失敗時,會拋出 bac_alloc 異常,不會返回 NULL;malloc 分配內存失敗時返回 NULL。
  • 使用 new 操作符申請內存分配時無須指定內存塊的大小,編譯器會根據類型信息自行計算,而 malloc 則需要顯式地指出所需內存的大小。
  • new/delete 會調用對象的構造函數/析構函數以完成對象的構造/析構。而 malloc 則不會。
  • C++ 提供了 new[] 與 delete[] 來專門處理數組類型,new 對數組的支持體現在它會分別調用構造函數初始化每一個數組元素,釋放對象時爲每個對象調用析構函數。至於 malloc,它並不知道你在這塊內存上要放的數組還是其他類型,它只分配一塊原始的內存,返回一個內存的地址。所以如果要動態分配一個數組的內存,還需要我們手動自定數組的大小。
  • operator new/operator delete 的實現可以基於 malloc,而 malloc 的實現不可以去調用 new。
  • opeartor new/operator delete 可以被重載。而 malloc/free 不允許重載。
  • 使用 malloc 分配的內存後,如果在使用過程中發現內存不足,可以使用 realloc 函數進行內存重新分配實現內存的擴充。new 沒有這樣直觀的配套設施來擴充內存。
  • 在 operator new 拋出異常以反映一個未獲得滿足的需求之前,它會先調用一個用戶指定的錯誤處理函數,這就是 new-handler。對於 malloc,客戶並不能夠去編程決定內存不足以分配時要幹什麼事,只能看着 malloc 返回 NULL。

堆和棧的區別

  • 管理方式不同:棧由操作系統自動分配釋放,無需我們手動控制;堆的申請和釋放工作由程序員控制,容易產生內存泄漏。
  • 申請後系統的響應不同:只要棧的剩餘空間大於所申請空間,系統將爲程序提供內存,否則將報異常提示棧溢出。對於堆來說,首先應該知道操作系統有一個記錄空閒內存地址的鏈表,當系統收到程序的申請時,會遍歷該鏈表,尋找第一個空間大於所申請空間的堆結點,然後將該結點從空閒結點鏈表中刪除,並將該結點的空間分配給程序。
  • 申請大小的限制不同:棧是向低地址擴展的數據結構,是一塊連續的內存的區域。棧頂的地址和棧的最大容量是系統預先規定好的,棧的大小是是一個編譯時就確定的常數,如果申請的空間超過棧的剩餘空間時,將提示 overflow。因此,能從棧獲得的空間較小。堆是向高地址擴展的數據結構,是不連續的內存區域。這是由於系統是用鏈表來存儲的空閒內存地址的,自然是不連續的,而鏈表的遍歷方向是由低地址向高地址。堆的大小受限於計算機系統中有效的虛擬內存。由此可見,堆獲得的空間比較靈活,也比較大。
  • 申請效率的比較不同: 棧由系統自動分配,速度較快。但程序員是無法控制的。 堆是由 new 分配的內存,一般速度比較慢,而且容易產生內存碎片。

sizeof 和 strlen 的區別

  • sizeof 是 C/C++ 語言的單目運算符,用來計算數據所佔內存的大小;而 strlen 是庫函數,用來計算字符串的長度。
  • sizeof 所計算的值在編譯階段就能確定,strlen 在運行時才能計算出結果。
  • 求字符串長度時,sizeof 返回的結果包含 ‘\0’,計算的是實際佔用內存的大小,而 strlen 不包括,但它也是根據 ‘\0’ 來判斷字符串結尾的。
  • sizeof 可以使用類型做參數, strlen 只能使用 char * 類型做參數,並且必須是以 ‘\0’ 結尾。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章