5-2 new、delete探祕,智能指針概述、shared_ptr

001newdelete探祕

#include<iostream>
#include<cstdlib>
#include<string>
#include<vector>

using namespace std;

class A
{
public:
	
	A()
	{
		cout << "構造函數被執行" << endl;
	}
	~A();
	
};
A::~A()
{
	cout << "析構函數被執行" << endl;
}


int main(void)
{
	//(1)
	A*a1 = new A();//調用類A的構造函數
	delete a1;//該類的析構函數被執行

	int *p1 = new int(100);
	delete p1;
	//operator new()  和operator delete()是函數
	/*
	 * new幹了兩個事情
	 * (1)在堆上分配內存,就是通過operator new()來分配內存
	 * (2)調用構造函數來初始化內存。
	 *delete也幹了兩個事情:
	 *(1)調用析構函數,做一些對象釋放前的操作
	 *(2)釋放內存 --調用operator delete()函數來釋放內存
	 */

	//operator new()函數可以直接調用
	void* myPoint = operator new (100);//直接分配100個字節


	//(2)
	int *p3 = new int(23);//分配4個字節
	delete p3;//刪除的時候,編譯器是怎麼知道要釋放4個字節???
	/*
	 * new出的內存空間中單獨分配空間來記錄分配的內存空間的大小,自己內部有記錄機制。不需要深入瞭解。
	 */
	
	//(3)申請和釋放一個數組  這些可以在MFC框架下演示
	int *p4 = new int[2];//int類型數組,有2個元素,佔有8個字節 沒有回收

	A a2;
	cout << sizeof(a2) << endl;//1  泄漏一個字節
	cout << sizeof(A) << endl;//1

	A*p5 = new A();//泄漏1字節

	A*p6 = new A[2]();//泄漏6個字節,比我們想的多出來4個字節
	
	/*
	 * 爲什麼空A對象a2佔有1個字節?
	 * 因爲每個對象分配了內存空間,至少佔有一個地址空間,至少佔有1個字節的地址。
	 *
	 *
	 * 疑問:爲什麼定義類型A數組會多泄漏,也就是給類型A對象數組多分配4個字節,而內置類型int並沒有多分配?
	 * 定義類對象數組,需要額外的4個字節來記錄是多少個數組元素,以便後面調用多少次析構函數,
	 */

	int *p7 = new int[3];
	delete p7;//沒有使用[],也可以釋放,沒有內存泄漏,但是建議使用delete []p7;

	A*p8 = new A[2]();//泄漏6字節,其中2個字節是對象數組,另外4個。。。是一個整形,記錄的是數組元素的個數,這裏是數字2
	delete[]p8;//類類型必須使用[],不使用會報異常  ----調用2次析構函數


	/*A*p9 = new A;
	delete[]p9;*/
	//系統一直調用析構函數,因爲不知道數組元素的個數
	
	system("pause");
	return 0;
}

/*
*(1)new delete探祕
*	1.sizeof new delete都是運算符,不是運算符
*	2.new delete是一對,malloc() free()是一對,new和delete會調用構造函數和析構函數。
*		也就是說new和delete具備對堆上所分配內存初始化,反初始化的能力。malloc 和free不具有這種能力。
*	總結:進行運算符的重載來進行函數operator new() operator delete()來進行不同數據類型的分配和釋放。
*	
*(2)基本new如何記錄分配的內存大小供delete使用?
*	不同編譯器new內部有不同的實現方式。
*
*(3)申請和釋放一個數組
*	new進行類對象數組分配的時候會額外佔用內存空間記錄數組個數,這裏是佔用4個字節記錄類對象數組的元素個數,
*	以便後面調用析構函數釋放多少次析構函數。
*	如果沒有析構函數,系統就不會額外分配內存空間記錄額外的類對象數組個數。
*
*(4)爲什麼對數組釋放內存不加[]就會報異常??
*A*p8 = new A[2]();
*delete[]p8;//這裏使用delete p8;就會報異常
*寫成delete p8;
*	1.只會調用一次析構函數只析構了一個對象,有內存泄漏
*	2.調用operator delete(p8)釋放內存的時候,因爲不知道數組元素的個數,會導致釋放內存錯亂。不知道釋放多少個內存空間。
*總結:new delete 和new[] delete[]配套使用
*
*
*
*/

002智能指針概述和shared_ptr基礎

#include<iostream>
#include<cstdlib>
#include<string>
#include<vector>
#include <memory>

using namespace std;

shared_ptr<int> testFunction(int value)
{
	//return new int();//error,不可以將new得到的int*類型轉換爲shared_ptr
	return shared_ptr<int>(new int(value));//OK,強制類型轉換
}

int main(void)
{
	//shared_ptr指針用法
	shared_ptr<int>p1(new int(100));//p1指向值爲100的int類型內存空間
									//shared_ptr<int>p2 = new int(100);//error智能指針是explicit,不可以進行隱式類型轉換,
									//=一般用於隱式類型zhuanhaun


									//返回值是shared_ptr
	shared_ptr<int> p2 = testFunction(234);

	//裸指針可以初始化shared_ptr,但是不推薦
	string* s1 = new string("23432434");
	shared_ptr<string>s2(s1);
	//建議使用
	shared_ptr<string>s3(new string("sdfdsf"));

	//空的shared_ptr指針
	shared_ptr<int>p3;//指向int的智能指針,但還是目前爲空==nullptr

					  //(3)make_shared
	shared_ptr<int>p4 = make_shared<int>(1345);//shared_ptr指向一個值爲100的整形內存空間。
	shared_ptr<string>p5 = make_shared<string>(5, 'a');//p5指向aaaaa的字符串內存空間
	shared_ptr<int>p6 = make_shared<int>();//p6指向一段內存空間int=0
	p6 = make_shared<int>(1000);
	/*p6指向一段新的int,先釋放指向0的內存空間,然後指向int值爲1000的內存空間。
	*
	*/

	system("pause");
	return 0;
}

/*
*ptr==pointer的縮寫
*
*(1)智能指針綜述
*常見錯誤
*if()
*{
*	.....
*	return ;
*}
*delete p;//執行不到這裏
*
*多個指針指向同一塊內存空間,釋放內存只能釋放一次。
*所以new delete的寫法要十分小心,要小小早早釋放,也小心忘記釋放。
*
*裸指針:直接new返回的指針。沒有經過任何包裝,這種指針強大,靈活,但是開發者要全程維護。
*引入智能指針解決裸指針的各種問題。
*智能指針:就理解成對裸指針進行了包裝,包裝後:
*最突出優點:智能指針“能夠自動釋放所指向的對象內存。”不用擔心new出來的內存忘記釋放。
*
*建議:優先使用智能指針,使用智能指針的程序更容易編寫和調試。
*
*c++中有4種智能指針:
*auto_ptr(c++98)
*unique_ptr(c++11)
*shared_ptr(c++11)
*weak_ptr(c++11)
*幫助我們進行動態分配對象的生命週期的管理,能夠有效防止內存泄漏。
*
*c++11標準中反對使用auto_ptr;目前auto——ptr已經完全被unique_ptr取代。
*c++11中的3種智能指針都是類模板,我們可以將new獲得的地址賦值給他們
*重點是shared_ptr:共享式指針--多個指針指向同一個對象,最後一個指針被銷燬時候,釋放對象的內存空間。
*weak_ptr是輔助shared_ptr;
*unique_ptr獨佔式指針,在一個時間內,只有一個指針能夠指向該對象,該對象的所有權是可以移交出去的。
*
*你忘記delete的時候,智能指針幫你delete,或者說,你不需要手動delete了。
*
*(2)shared_ptr基礎
*共享所有權--不是被一個shared_ptr擁有,而是多個shared_ptr之間相互協作。
*工作原理:引用計數,每個shared_ptr都指向相同的內存,所以最後一個指向不需要指向該對象的時候。
*那麼最後一個share_ptr去釋放該對象。
*
*最後一個指向對象的shared_ptr在什麼情況下釋放該對象(shared_ptr所指向的對象)?
*	1.shared_ptr聲明週期結束,被析構時候
*	2.這個shared_ptr指向其他對象的時候。
*	這種操作類似於java中的垃圾回收機制。
*是類模板,<>裏面就是指針可以指向的類型,後邊再跟智能指針名字
*格式:shared_ptr<指向的類型>智能指針名字
*
*
*(3)make_shared函數,標準庫裏面的函數模板,安全高效分配和使用shared_ptr
*能夠在堆中分配內存並初始化一個對象,然後返回指向此對象的shared_ptr
*make_shared不能自定義刪除器,因此需要自定義刪除器的時候,不能使用。
*
*/
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章