【從C到C++】------- C++的內存管理


爲什麼要研究內存管理


1、程序就是數據加算法
(1)寫程序是爲了解決某個問題,生活中的問題最終被計算機抽象爲控制或運算
(2)CPU中的主要構件就是運算器和控制器,本質上是一堆組合邏輯電路,表現爲機器指令集
(3)一個問題對應一個程序,一個程序分爲多個函數,一個函數分爲多個機器指令
(4)存儲機器指令需要內存機器指令的執行過程需要內存參與,這是內存的2大作用
(5)算法對應機器指令(ROM內存),數據對應RAM內存,CPU對應工作機器
(6)越是偏底層的語言,越對內存管理具體化,效率也越高,同時對編程者要求也越高

2、計算機中如何管理內存
(1)C++項目大多數對應在操作系統中運行,很少有裸機的
(2)OS提供最基本的內存管理體系,OS直接管理物理內存,並嚮應用層提供一套內存接口
(3)C++語言對OS的內存接口進行封裝,提供給編程者一套內存使用方法
(4)編程人員寫的代碼在編譯工具鏈、運行時、OS等體系的幫助下最終在計算機物理層運行

3、總結
(1)內存管理的原理雖然龐大而複雜,然而程序員只需要掌握好C++語言的內存管理語言特性即可
(2)C++程序容易出bug,主要就是因爲內存管理部分的複雜性
(3)Java,python等語言提供了更多的封裝,所以降低了程序員操作難度和犯錯可能性


C++可用內存區域


1、C語言可用內存區域
(1)棧,對應局部變量
(2)全局數據區/靜態數據區,對應全局變量,靜態局部變量
(3)const數據區,在內存層面是不存在的,是C編譯器營造出來的
(4)代碼段,放可執行程序的,性質是rom
(5)堆heap,由malloc和free來管理的一塊內存

2、C++新增內存區域
(1)自由存儲區由new申請得到的動態內存區域
(2)new操作符使用舉例

#include <iostream>

using namespace std;

int a;				// a是分配在全局數據區

int main(void)
{
		// C裏面mallolc
  	int a1;			// a1是分配在棧上面
  
	// 指針p是指向的內存分配在堆中,指針p自身是分配在棧上的
	int *p = (int *)malloc(4);		
	*p = 5;		// 使用p指向的那4個字節的內存
	free(p);	// 釋放p指向的那4個字節的內存
	
// C++中用新關鍵字new和delete替代了malloc和free
	int *p1 = new int(53);	// p1本身分配在棧上,p1指向的是一個int類型的數,佔4字節,同時初始化爲53
//	double *p1 = new double; // 這4個字節分配在自由存儲區
//	*p1 = 5.6;				  // 使用p指向的那4個字節的內存
	cout << "p = " << p << ", *p = " << *p << endl;
	delete p;			// 釋放p指向的那4個字節的內存	
	return 0;
}

3、new和malloc的區別
(1)malloc是C庫函數,new是C++運算符關鍵字
(2)malloc申請空間大小靠傳參確定,而new不需要傳參,對象本身大小由編譯器自動計算給出
(3)malloc返回值爲void *因此需要強轉,而new返回值類型爲確定的對象指針類型
(4)malloc對應free釋放,new對應delete和delete[]釋放

(5)malloc只能申請內存不能帶初始化,而new可以帶初始化
(6)new會執行類的構造函數而malloc不會
(7)malloc失敗返回NULL,而new失敗引發bad_alloc異常
(8)申請和釋放數組類型時不同

4、總結
(1)代碼段只會讀不會寫,一般不會出任何問題
(2)全局數據區和棧區都是自動管理的,只要可用內存足夠不會出問題
(3)const數據區實際上是由編譯器來保證只讀的,本質就是普通的內存區域
(4)靈活性和風險都集中在heap區域,常見問題如內存泄漏、內存碎片等
(5)linux平臺中new內部是通過malloc實現的,new比malloc多一個調用構造函數
(6)malloc只是返回一塊荒地給你,而new會給你修好路蓋好房子規劃好田地等

智能指針的簡單引入

1、指針的優勢和劣勢
(1)指針的本質是一個變量,變量的值是其他對象的地址,因此可以解引用
(2)指針本質上對應CPU指令中的間接尋址,所以指針是天然存在的,是CPU設計決定了的
(3)指針的優勢就是靈活、代碼效率高
(4)指針的劣勢是太靈活,尤其結合動態內存和構造、析構後,在複雜業務中容易出錯

2、如何解決
(1)底層不用指針是不可能的,因此這個問題是繞不開的
(2)解決方案1:由程序員來自主把控,C/C++典型編程就是這樣
(3)解決方案2:由程序員和專門設計的自動管理機制共同把控,典型代表是智能指針
(4)解決方案3:由自動管理機制全權把控,程序員不用管,典型代表是Java的垃圾回收機制

3、智能指針如何實現
(1)將普通的簡單純指針封裝爲棧式複合指針對象,即智能指針對象
(2)智能指針本身定義爲局部變量,分配在棧內存上,因此本身是自動回收的
(3)智能指針內部設計爲當智能指針本身要被彈棧釋放時,執行事先掛接好的清理函數
(4)智能指針的正常使用通過一些提供的方法和運算符重載來使用

4、智能指針總結
(1)智能指針是普通指針的升級版,封裝版,本身具備指針的功能,且多出一些自動釋放資源機制
(2)智能指針進行動態內存管理,要比普通指針多出很多(內存和性能上的)開銷。
(3)智能指針的實現不是唯一的,C++有很多智能指針,各有優劣和適用場景,如:std::auto_ptr、boost::scoped_ptr、boost::shared_ptr、boost::scoped_array、boost::shared_array、boost::weak_ptr、boost::intrusive_ptr。
(4)智能指針也要按照設計去正確使用,否則也會出問題。具體用法後續課程再講。


Java的垃圾回收機制介紹


1、Java語言整體框架
(1)CPU->操作系統內核->應用層框架->JVM(java虛擬機)->Java字節碼->Java源代碼
(2)Java是解釋型語言,而非編譯型語言
(3)Java虛擬機是Java語言的運行時環境,也是Java語言跨平臺的關鍵

2、Java的垃圾回收機制介紹
(1)什麼是垃圾?待回收的內存資源,本質是生命週期結束了的變量對象等。
(2)誰來回收?GC線程,Java虛擬機中的守護線程。
(3)什麼時候回收?GC機制和算法來決定,程序員不用管。
(4)如何確定誰是垃圾?引用計數法和可達性分析法。

Java的垃圾回收機制引用計數法和可達性分析法

3、垃圾回收機制點評
(1)不止java,其他語言如C#也是類似設計理念,典型特徵就是語言沒有指針的概念
(2)垃圾回收機制讓程序員免於考慮對象的生命週期和資源的申請與釋放,編程難度大減。
(3)垃圾回收機制的穩定性和效率取決於運行時環境(JVM等)設計和實現的好壞
(4)垃圾回收機制用效率和內存資源成本,換來了更簡單不易錯的語言特性。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章