柚子快報(bào)激活碼778899分享:開發(fā)語言 C++-詳解智能指針
柚子快報(bào)激活碼778899分享:開發(fā)語言 C++-詳解智能指針
?
目錄
?編輯
一.什么是智能指針
? ? ? ? 1.RAII
? ? ? ? 2.智能智能指針
二.為什么需要智能指針
? ? ? ? 1.內(nèi)存泄漏
? ? ? ? ? ? ? ?a.?什么是內(nèi)存泄漏,內(nèi)存泄漏的危害
????????? ? ? ? b.內(nèi)存泄漏分類
????????????????c.如何檢測(cè)內(nèi)存泄漏
????????????????d.如何避免內(nèi)存泄漏
????????????????總結(jié)一下:
? ? ? ? 2.為什么需要智能指針以及智能指針的原理
三.智能指針的使用
? ? ? ? 1.C++98中的敗筆智能指針auto_ptr
????????2.C++11中的智能指針
? ? ? ? ? ? ? ? a.unique_ptr?不可拷貝的智能指針
? ? ? ? ? ? ? ? b.share_ptr 可以拷貝的智能指針????????
? ? ? ? c.weak_ptr 用來解決share_ptr中的循環(huán)引用問題
?
一.什么是智能指針
? ? ? ? 1.RAII
????????????????RAII(Resource Acquisition Is Initialization
)是一種
利用對(duì)象生命周期來控制程序資源
(如內(nèi)存、文件句柄、網(wǎng)絡(luò)連接、互斥量等等)的簡(jiǎn)單技術(shù)。在對(duì)象構(gòu)造時(shí)獲取資源
,接著控制對(duì)資源的訪問使之在對(duì)象的生命周期內(nèi)始終保持有效,
最后在
對(duì)象析構(gòu)的時(shí)候釋放資源
。借此,我們實(shí)際上把管理一份資源的責(zé)任托管給了一個(gè)對(duì)象。這種做法有兩大好處:
????????????????不需要顯式地釋放資源。
????????????????采用這種方式,對(duì)象所需的資源在其生命期內(nèi)始終保持有效
? ? ? ? 2.智能智能指針
?????????????????在程序中創(chuàng)建一個(gè)專門管理在程序中申請(qǐng)資源的類,通過這個(gè)類管理我們申請(qǐng)的資源。
二.為什么需要智能指針
? ? ? ? 1.內(nèi)存泄漏
? ? ? ? ? ? ? ?a.?什么是內(nèi)存泄漏,內(nèi)存泄漏的危害
????????什么是內(nèi)存泄漏:內(nèi)存泄漏指因?yàn)槭韬龌蝈e(cuò)誤造成程序未能釋放已經(jīng)不再使用的內(nèi)存的情況。內(nèi) 存泄漏并不是指內(nèi)存在物理上的消失,而是應(yīng)用程序分配某段內(nèi)存后,因?yàn)樵O(shè)計(jì)錯(cuò)誤,失去了對(duì) 該段內(nèi)存的控制,因而造成了內(nèi)存的浪費(fèi)。
????????內(nèi)存泄漏的危害:長(zhǎng)期運(yùn)行的程序出現(xiàn)內(nèi)存泄漏,影響很大,如操作系統(tǒng)、后臺(tái)服務(wù)等等,出現(xiàn) 內(nèi)存泄漏會(huì)導(dǎo)致響應(yīng)越來越慢,最終卡死。
????????
?
void MemoryLeaks()
{
? // 1.內(nèi)存申請(qǐng)了忘記釋放
?int* p1 = (int*)malloc(sizeof(int));
?int* p2 = new int;
?
?// 2.異常安全問題
?int* p3 = new int[10];
?
?Func(); // 這里Func函數(shù)拋異常導(dǎo)致 delete[] p3未執(zhí)行,p3沒被釋放.
?
?delete[] p3;
}
????????? ? ? ? b.內(nèi)存泄漏分類
????????????????????????C/C++程序中一般我們關(guān)心兩種方面的內(nèi)存泄漏:
????????????????????????堆內(nèi)存泄漏(Heap leak)
????????????????????????????????堆內(nèi)存指的是程序執(zhí)行中依據(jù)須要分配通過malloc / calloc / realloc / new等從堆中分配的一塊內(nèi)存,用完后必須通過調(diào)用相應(yīng)的 free
或者
delete
刪掉。假設(shè)程序的設(shè)計(jì)錯(cuò)誤導(dǎo)致這部分內(nèi)存沒有被釋放,那么以后這部分空間將無法再被使用,就會(huì)產(chǎn)生Heap Leak
。
????????????????????????系統(tǒng)資源泄漏
????????????????????????????????指程序使用系統(tǒng)分配的資源,比方套接字、文件描述符、管道等沒有使用對(duì)應(yīng)的函數(shù)釋放掉,導(dǎo)致系統(tǒng)資源的浪費(fèi),嚴(yán)重可導(dǎo)致系統(tǒng)效能減少,系統(tǒng)執(zhí)行不穩(wěn)定。
????????????????c.如何檢測(cè)內(nèi)存泄漏
????????????????????????在linux下內(nèi)存泄漏檢測(cè):
linux
下幾款內(nèi)存泄漏檢測(cè)工具
????????????????????????在windows下使用第三方工具:
VLD
工具說明
????????????????????????其他工具:
內(nèi)存泄漏工具比較
????????????????d.如何避免內(nèi)存泄漏
????????????????????????1. 工程前期良好的設(shè)計(jì)規(guī)范,養(yǎng)成良好的編碼規(guī)范,申請(qǐng)的內(nèi)存空間記著匹配的去釋放。ps:這個(gè)理想狀態(tài)。但是如果碰上異常時(shí),就算注意釋放了,還是可能會(huì)出問題。需要下一條智能指針來管理才有保證。
????????????????????????2. 采用RAII思想或者智能指針來管理資源
? ? ? ? ? ? ? ? ? ??
????????????????????????3. 有些公司內(nèi)部規(guī)范使用內(nèi)部實(shí)現(xiàn)的私有內(nèi)存管理庫。這套庫自帶內(nèi)存泄漏檢測(cè)的功能選項(xiàng)。
????????????????????????4. 出問題了使用內(nèi)存泄漏工具檢測(cè)。ps:不過很多工具都不夠靠譜,或者收費(fèi)昂貴。
????????????????總結(jié)一下:
????????????????????????內(nèi)存泄漏非常常見,解決方案分為兩種:1、事前預(yù)防型。如智能指針等。2
、事后查錯(cuò)型。如泄 漏檢測(cè)工具
? ? ? ? 2.為什么需要智能指針以及智能指針的原理
????????????????
? ????????????????先來看這樣一段代碼:
????????
#include
#include
using namespace std;
int main(void)
{
string* str_ptr = new string;
func();
delete str_ptr;
return 0;
}
? ? ? ? ????????對(duì)于上面的代碼,關(guān)于str_ptr中申請(qǐng)的堆中的資源,此時(shí)我們需要手動(dòng)釋放,那么當(dāng)程序沒有問題的運(yùn)行完成時(shí),此時(shí)程序完成對(duì)我們申請(qǐng)的資源的釋放,但是如果在中間的func()函數(shù)發(fā)生錯(cuò)誤拋異常了,會(huì)改變我們程序的執(zhí)行順序,此時(shí)我們釋放代碼就不會(huì)被執(zhí)行了。
? ? ? ? ? ? ? ? 此時(shí)我們就會(huì)想如果有一個(gè)可以自己知道自己什么該死的空間就好了。
? ? ? ? ? ? ? ? 此時(shí)就有人提出智能指針的概念了。
? ? ? ? ? ? ? ? 通過一個(gè)類來管理我們申請(qǐng)的資源,該類的析構(gòu)函數(shù)在類對(duì)象出作用域的時(shí)候會(huì)自動(dòng)被調(diào)用,會(huì)自動(dòng)的清理我們的資源。
template
class SmartPtr {
public:
? ?SmartPtr(T* ptr = nullptr)
? ? ? : _ptr(ptr)
? {}
? ?~SmartPtr()
? {
? ? ? ?if(_ptr)
? ? ? ? ? ?delete _ptr;
? }
? ?
private:
? ?T* _ptr;
};
int div()
{
int a, b;
cin >> a >> b;
if (b == 0)
throw invalid_argument("除0錯(cuò)誤");
return a / b;
}
void Func()
{
ShardPtr
? ShardPtr
cout << div() << endl;
}
int main()
{
? ?try {
Func();
? }
? ?catch(const exception& e)
? {
? ? ? ?cout< ? } return 0; } 三.智能指針的使用 ???????? ? ? ? ? 1.C++98中的敗筆智能指針auto_ptr #include #include using namespace std; class A { public: A(int a) :_a(a) { cout << "A()" << endl; } ~A() { cout << "~A()" << endl; } private: int _a; }; int main(void) { auto_ptr ap1(new A(1)); auto_ptr ap2(new A(2)); auto_ptr ap3; ap3 = ap1; return 0; } ? ? ? ? ? ? ? ? 此時(shí)我們發(fā)現(xiàn)這個(gè)auto_ptr在進(jìn)行拷貝的時(shí)候是轉(zhuǎn)移資源的使用權(quán),此后我們?cè)谑褂胊p1 這個(gè)智能指針的時(shí)候就無法使用了。 ? ????????2.C++11中的智能指針 ? ? ? ? ? ? ? ? a.unique_ptr?不可拷貝的智能指針 ???????????????????????? ? ? ? ? ? ? ? ? ? ?類的對(duì)象不可以進(jìn)行拷貝的兩個(gè)方法: ? ? ? ? ? ? ? ? ? ? ? ? ? 將該類的拷貝構(gòu)造函數(shù)私有化。 ? ? ? ? ? ? ? ? ? ? ? ? ? unique_ptr(unique_ptr template class unique_ptr { public: // RAII // 像指針一樣 unique_ptr(T* ptr) :_ptr(ptr) {} ~unique_ptr() { cout << "delete:" << _ptr << endl; delete _ptr; } T& operator*() { return *_ptr; } T* operator->() { return _ptr; } // ap3(ap1) // 管理權(quán)轉(zhuǎn)移 // 防拷貝 unique_ptr(unique_ptr unique_ptr private: T* _ptr; }; ? ? ? ? ? ? ? ? b.share_ptr 可以拷貝的智能指針???????? ?????????????????????????? ? template class shared_ptr { public: // RAII // 像指針一樣 shared_ptr(T* ptr = nullptr) :_ptr(ptr) ,_pcount(new int(1)) {} // function template shared_ptr(T* ptr, D del) :_ptr(ptr) , _pcount(new int(1)) , _del(del) {} ~shared_ptr() { if (--(*_pcount) == 0) { cout << "delete:" << _ptr << endl; //delete _ptr; _del(_ptr); delete _pcount; } } T& operator*() { return *_ptr; } T* operator->() { return _ptr; } // sp3(sp1) shared_ptr(const shared_ptr :_ptr(sp._ptr) ,_pcount(sp._pcount) { ++(*_pcount); } // sp1 = sp5 // sp6 = sp6 // sp4 = sp5 shared_ptr { if (_ptr == sp._ptr) return *this; if (--(*_pcount) == 0) { delete _ptr; delete _pcount; } _ptr = sp._ptr; _pcount = sp._pcount; ++(*_pcount); return *this; } int use_count() const { return *_pcount; } T* get() const { return _ptr; } private: T* _ptr; int* _pcount; function }; ? ? ? ? c.weak_ptr 用來解決share_ptr中的循環(huán)引用問題 ???????????????? ???????????????? ? template class weak_ptr { public: weak_ptr() :_ptr(nullptr) {} weak_ptr(const shared_ptr :_ptr(sp.get()) {} weak_ptr { _ptr = sp.get(); return *this; } T& operator*() { return *_ptr; } T* operator->() { return _ptr; } private: T* _ptr; }; 四.定制刪除器 ? ? ? ? 上面的代碼沒法自動(dòng)釋放new到的多個(gè)空間 ???????????????? ? ? ? ? ???解決方法 : ???????????????? ? ? 柚子快報(bào)激活碼778899分享:開發(fā)語言 C++-詳解智能指針 文章鏈接
本文內(nèi)容根據(jù)網(wǎng)絡(luò)資料整理,出于傳遞更多信息之目的,不代表金鑰匙跨境贊同其觀點(diǎn)和立場(chǎng)。
轉(zhuǎn)載請(qǐng)注明,如有侵權(quán),聯(lián)系刪除。