做網(wǎng)站廊坊百度網(wǎng)盤app下載安裝
目錄
1. 為什么需要智能指針?
2. 內(nèi)存泄漏
2.1 什么是內(nèi)存泄漏,內(nèi)存泄漏的危害
2.2 內(nèi)存泄漏分類(了解)
堆內(nèi)存泄漏(Heap leak)
系統(tǒng)資源泄漏
2.3 如何檢測(cè)內(nèi)存泄漏(了解)
2.4如何避免內(nèi)存泄漏
3.智能指針的使用及原理
3.1 RAII
// 使用RAII思想設(shè)計(jì)的SmartPtr類
?編輯
std::auto_ptr
模擬實(shí)現(xiàn)
std::unique_ptr
?編輯
?編輯
模擬實(shí)現(xiàn)
?編輯
模擬實(shí)現(xiàn)
?賦值(重要)
總代碼?
循環(huán)引用問題
解決方法(weak_ptr不是智能指針)
模擬實(shí)現(xiàn)
測(cè)試:?編輯
功能
語法
優(yōu)點(diǎn)
示例
注意事項(xiàng)
定制刪除器(用到了包裝器)
?題目
1. 為什么需要智能指針?
下面我們先分析一下下面這段程序有沒有什么內(nèi)存方面的問題?提示一下:注意分析MergeSort函數(shù)中的問題。
因?yàn)閐iv拋異常后會(huì)跳過delete,導(dǎo)致內(nèi)存泄漏
int div()
{int a, b;cin >> a >> b;if (b == 0)throw invalid_argument("除0錯(cuò)誤");return a / b;
}void Func()
{// 1、如果p1這里new 拋異常會(huì)如何?// 2、如果p2這里new 拋異常會(huì)如何?// 3、如果div調(diào)用這里又會(huì)拋異常會(huì)如何?int* p1 = new int;int* p2 = new int;cout << div() << endl;delete p1;delete p2;
}int main()
{try{Func();}catch (exception& e){cout << e.what() << endl;}return 0;
}
2. 內(nèi)存泄漏
2.1 什么是內(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;
}
2.2 內(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)定。
2.3 如何檢測(cè)內(nèi)存泄漏(了解)
在linux下內(nèi)存泄漏檢測(cè):Linux下幾款C++程序中的內(nèi)存泄露檢查工具_(dá)c++內(nèi)存泄露工具分析-CSDN博客
在windows下使用第三方工具:VS編程內(nèi)存泄漏:VLD(Visual LeakDetector)內(nèi)存泄露庫(kù)_visual leak detector vs2020-CSDN博客
其他工具:內(nèi)存泄露檢測(cè)工具比較 - 默默淡然 - 博客園
2.4如何避免內(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)存管理庫(kù)。這套庫(kù)自帶內(nèi)存泄漏檢測(cè)的功能選項(xiàng)。
4. 出問題了使用內(nèi)存泄漏工具檢測(cè)。ps:不過很多工具都不夠靠譜,或者收費(fèi)昂貴。 總結(jié)一下:
內(nèi)存泄漏非常常見,解決方案分為兩種:1、事前預(yù)防型。如智能指針等。2、事后查錯(cuò)型。如泄 漏檢測(cè)工具。
3.智能指針的使用及原理
3.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)始終保持有效。
// 使用RAII思想設(shè)計(jì)的SmartPtr類
int div()
{int a, b;cin >> a >> b;if (b == 0)throw invalid_argument("除0錯(cuò)誤");return a / b;
}
//這樣就不用擔(dān)心沒有釋放了
template<class T>
class SmartPtr
{
public:// RAII// 資源交給對(duì)象管理,對(duì)象生命周期內(nèi),資源有效,對(duì)象生命周期到了,釋放資源// 1、RAII管控資源釋放// 2、像指針一樣SmartPtr(T* ptr):_ptr(ptr){}~SmartPtr(){cout << "delete:" << _ptr << endl;delete _ptr;}T& operator*(){return *_ptr;}T* operator->(){return _ptr;}
private:T* _ptr;
};
void f()
{//new,也可能有很小的概率出問題SmartPtr<pair<string, string>> sp1(new pair<string, string>("1111", "22222"));//這里div拋異常后,sp1會(huì)釋放,然后直接跳過進(jìn)入main中不進(jìn)入,sp2,sp3,只要是f結(jié)束,f中的new后都//會(huì)調(diào)用deletediv();SmartPtr<pair<string, string>> sp2(new pair<string, string>);SmartPtr<pair<string, string>> sp3(new pair<string, string>);SmartPtr<string> sp4(new string("xxxxx"));/*cout << *sp4 << endl;cout << sp1->first << endl;cout << sp1->second << endl;*///這里div拋異常后,sp1和sp2,sp3都會(huì)釋放div();//delete p1;//cout << "delete:" << p1 << endl;
}
int main()
{try{f();}catch (const exception& e){cout << e.what() << endl;}catch (...){cout << "Unkown Exception" << endl;}return 0;
}
沒寫賦值,淺拷貝(深拷貝也沒法解決問題),把sp2的值給了sp1,只釋放了一個(gè),還有一個(gè)沒釋放,發(fā)生了內(nèi)存泄漏?
c++中new了要delete
有了異常以后,已經(jīng)不可控了,因?yàn)閽伄惓?huì)影響執(zhí)行流,會(huì)改變程序執(zhí)行順序
智能指針
using namespace std;
int div()
{int a, b;cin >> a >> b;if (b == 0)throw invalid_argument("除0錯(cuò)誤");return a / b;
}
//這樣就不用擔(dān)心沒有釋放了
template<class T>
class SmartPtr
{
public:// RAII// 資源交給對(duì)象管理,對(duì)象生命周期內(nèi),資源有效,對(duì)象生命周期到了,釋放資源// 1、RAII管控資源釋放// 2、像指針一樣SmartPtr(T* ptr):_ptr(ptr){}~SmartPtr(){cout << "delete:" << _ptr << endl;delete _ptr;}T& operator*(){return *_ptr;}T* operator->(){return _ptr;}
private:T* _ptr;
};
void f()
{//new,也可能有很小的概率出問題SmartPtr<pair<string, string>> sp1(new pair<string, string>("1111", "22222"));//這里div拋異常后,sp1會(huì)釋放,然后直接跳過進(jìn)入main中不進(jìn)入,sp2,sp3,只要是f結(jié)束,f中的new后都//會(huì)調(diào)用deletediv();SmartPtr<pair<string, string>> sp2(new pair<string, string>);SmartPtr<pair<string, string>> sp3(new pair<string, string>);SmartPtr<string> sp4(new string("xxxxx"));/*cout << *sp4 << endl;cout << sp1->first << endl;cout << sp1->second << endl;*///這里div拋異常后,sp1和sp2,sp3都會(huì)釋放div();//delete p1;//cout << "delete:" << p1 << endl;}int main()
{try{f();}catch (const exception& e){cout << e.what() << endl;}catch (...){cout << "Unkown Exception" << endl;}return 0;
}
std::auto_ptr
文檔??https://cplusplus.com/reference/memory/auto_ptr/
auto_ptr是一個(gè)失敗設(shè)計(jì),很多公司明確要求不能使用auto_ptr
會(huì)導(dǎo)致懸空問題,實(shí)質(zhì)上是管理權(quán)限的轉(zhuǎn)移
C++98版本的庫(kù)中就提供了auto_ptr的智能指針。下面演示的auto_ptr的使用及問題。
auto_ptr的實(shí)現(xiàn)原理:管理權(quán)轉(zhuǎn)移的思想,下面簡(jiǎn)化模擬實(shí)現(xiàn)了一份bit::auto_ptr來了解它的原 理
// C++98 管理權(quán)轉(zhuǎn)移 auto_ptr
int main()
{//這種形式跟上面自己寫的Smartptr類似auto_ptr<int> at1(new int);//這個(gè)auto_ptr拷貝后會(huì)出現(xiàn)大問題,會(huì)出現(xiàn)懸空問題auto_ptr<int> at2(at1);//管理權(quán)限的轉(zhuǎn)移*at2 = 10;cout << *at2 << endl;//*at1 = 10;會(huì)報(bào)錯(cuò),因?yàn)?at1已經(jīng)懸空*at1 = 10;cout << *at1 << endl;return 0;
}
模擬實(shí)現(xiàn)
namespace Ljw
{template<class T>class auto_ptr{public:auto_ptr(T* ptr):_ptr(ptr){}~auto_ptr(){cout << "~auto_ptr" << endl;if (_ptr){delete _ptr;}}T& operator*(){return *_ptr;}T* operator->(){return _ptr;}//重點(diǎn)在于拷貝auto_ptr(auto_ptr<T>& ptr):_ptr(ptr._ptr){//這里就是懸空了,管理權(quán)轉(zhuǎn)ptr._ptr = nullptr;}private:T* _ptr;};
}
std::unique_ptr
C++11中開始提供更靠譜的unique_ptr
文檔:https://cplusplus.com/reference/memory/unique_ptr/
unique_ptr的實(shí)現(xiàn)原理:簡(jiǎn)單粗暴的防拷貝,下面簡(jiǎn)化模擬實(shí)現(xiàn)了一份UniquePtr來了解它的原 理
/ C++11庫(kù)才更新智能指針實(shí)現(xiàn)
// C++11出來之前,boost搞除了更好用的scoped_ptr/shared_ptr/weak_ptr // C++11將boost庫(kù)中智能指針精華部分吸收了過來
// C++11->unique_ptr/shared_ptr/weak_ptr // unique_ptr/scoped_ptr // 原理:簡(jiǎn)單粗暴 -- 防拷貝
模擬實(shí)現(xiàn)
template<class T>
class unique_ptr
{
public://默認(rèn)構(gòu)造unique_ptr(T*ptr):_ptr(ptr){}~unique_ptr(){delete _ptr;}T& operator*(){return *_ptr;}T* operator->(){return _ptr;}//直接用delete禁止拷貝構(gòu)造unique_ptr(unique_ptr<T>& ptr) = delete;//直接用delete禁止賦值unique_ptr<T>& operator=(unique_ptr<T>& ptr) = delete;
private:T* _ptr;
};
std::shared_ptr
C++11中開始提供更靠譜的并且支持拷貝的shared_ptr
文檔:https://cplusplus.com/reference/memory/shared_ptr/
shared_ptr的原理:是通過引用計(jì)數(shù)的方式來實(shí)現(xiàn)多個(gè)shared_ptr對(duì)象之間共享資源。例如: 老師晚上在下班之前都會(huì)通知,讓最后走的學(xué)生記得把門鎖下。
1. shared_ptr在其內(nèi)部,給每個(gè)資源都維護(hù)了著一份計(jì)數(shù),用來記錄該份資源被幾個(gè)對(duì)象共 享。
2. 在對(duì)象被銷毀時(shí)(也就是析構(gòu)函數(shù)調(diào)用),就說明自己不使用該資源了,對(duì)象的引用計(jì)數(shù)減 一。
3. 如果引用計(jì)數(shù)是0,就說明自己是最后一個(gè)使用該資源的對(duì)象,必須釋放該資源;
4. 如果不是0,就說明除了自己還有其他對(duì)象在使用該份資源,不能釋放該資源,否則其他對(duì)象就成野指針了。
// 引用計(jì)數(shù)支持多個(gè)拷貝管理同一個(gè)資源,最后一個(gè)析構(gòu)對(duì)象釋放資源
原理圖
模擬實(shí)現(xiàn)
用指針創(chuàng)建空間進(jìn)行計(jì)數(shù)保存是合理的,靜態(tài)全局的也是不符合的。
重點(diǎn)
?賦值(重要)
步驟1:先把sp1和sp3弄成共同資源,先把sp2和sp4和sp5弄成共同資源
經(jīng)過測(cè)試后,實(shí)際只有釋放一個(gè)空間
//賦值
//要考慮到前后計(jì)數(shù)要改變
//如果到0了也是需要直接釋放的
//如果是同一塊資源賦值可以不用處理
//同一塊資源的判定條件是
shared_ptr<T>& operator=(shared_ptr<T>& ptr)
{//同一塊資源if (_ptr == ptr._ptr)return *this;//賦值的時(shí)候,this的空間計(jì)數(shù)就少了1(*_count)--;if (*(_count) == 0){delete _ptr;delete _count;}//先增加計(jì)數(shù)也一樣然后ptr的空間資源計(jì)數(shù)就多了1//(*ptr._count)++;//賦值_ptr = ptr._ptr;_count = ptr._count;//然后ptr的空間資源計(jì)數(shù)就多了1(*_count)++;return *this;
}
總代碼?
template<class T>
class shared_ptr
{
public://默認(rèn)構(gòu)造shared_ptr(T* ptr=nullptr):_ptr(ptr),_count(new int(1))//這里_count是指針,要單獨(dú)開一個(gè)空間,進(jìn)行管理{}~shared_ptr(){(*_count)--;if ((* _count) == 0){cout << "~shared_ptr" << endl;delete _ptr;delete _count;} }T& operator*(){return *_ptr;}T* operator->(){return _ptr;}//sp2(sp1)shared_ptr(shared_ptr<T>& ptr):_ptr(ptr._ptr),_count(ptr._count){(*_count)++;}//賦值//要考慮到前后計(jì)數(shù)要改變//如果到0了也是需要直接釋放的//如果是同一塊資源賦值可以不用處理//同一塊資源的判定條件是shared_ptr<T>& operator=(shared_ptr<T>& ptr){//同一塊資源if (_ptr == ptr._ptr)return *this;//賦值的時(shí)候,this的空間計(jì)數(shù)就少了1(*_count)--;if (*(_count) == 0){delete _ptr;delete _count;}//先增加計(jì)數(shù)也一樣然后ptr的空間資源計(jì)數(shù)就多了1//(*ptr._count)++;//賦值_ptr = ptr._ptr;_count = ptr._count;//然后ptr的空間資源計(jì)數(shù)就多了1(*_count)++;return *this;}int use_count() const{return *_count;}T* get() const{return _ptr;}
private:T* _ptr;//計(jì)數(shù)int* _count;
};
循環(huán)引用問題
Node手動(dòng)釋放版本
delete n1上面如果拋異常了呢,所以就需要智能指針
這里報(bào)錯(cuò)的原因(類型不匹配)是因?yàn)橐粋€(gè)自定義類型一個(gè)內(nèi)置類型,要把上面的也改成智能指針,所以要改成如下圖
正常釋放(shared_ptr)
這樣就發(fā)生了循環(huán)引用,沒法正常釋放空間,屏蔽其中一個(gè)就沒問題,但兩個(gè)都有就不行了
解決方法(weak_ptr不是智能指針)
/ 解決方案:在引用計(jì)數(shù)的場(chǎng)景下,把節(jié)點(diǎn)中的_prev和_next改成weak_ptr就可以了
// 原理就是,node1->_next = node2;和node2->_prev = node1;時(shí)weak_ptr的_next和
_prev不會(huì)增加node1和node2的引用計(jì)數(shù)。
模擬實(shí)現(xiàn)
template<class T>
class weak_ptr
{
public:weak_ptr():_ptr(nullptr){}weak_ptr(const shared_ptr<T>& sp):_ptr(sp.get()){}weak_ptr<T>& operator=(const shared_ptr<T>& sp){_ptr = sp.get();return *this;}T& operator*(){return *_ptr;}T* operator->(){return _ptr;}
private:T* _ptr;
};
測(cè)試:
make_shared
make_shared
?是 C++11 標(biāo)準(zhǔn)庫(kù)中引入的一個(gè)模板函數(shù),它屬于?<memory>
?頭文件中定義的智能指針工具集。make_shared
?的主要目的是簡(jiǎn)化智能指針的創(chuàng)建過程,并可能提供性能上的優(yōu)化。
以下是?make_shared
?的一些關(guān)鍵點(diǎn):
功能
make_shared
?用于創(chuàng)建一個(gè)?std::shared_ptr
?對(duì)象,該對(duì)象管理動(dòng)態(tài)分配的對(duì)象。- 它接受一個(gè)類型參數(shù)以及該類型構(gòu)造函數(shù)所需的參數(shù),并返回一個(gè)?
shared_ptr
?指向新創(chuàng)建的對(duì)象。
語法
template< class T, class... Args >
shared_ptr<T> make_shared( Args&&... args );
優(yōu)點(diǎn)
-
簡(jiǎn)潔性:
make_shared
?允許你在一條語句中創(chuàng)建和管理動(dòng)態(tài)分配的對(duì)象,而不需要分別寫?new
?和?shared_ptr
?的構(gòu)造函數(shù)。 -
性能優(yōu)化:
make_shared
?通常比直接使用?new
?分配內(nèi)存再包裝成?shared_ptr
?更高效。這是因?yàn)?make_shared
?只需要在堆上分配一次內(nèi)存,即同時(shí)為對(duì)象本身和共享的引用計(jì)數(shù)(控制塊)分配空間。而直接使用?new
?和?shared_ptr
?的構(gòu)造函數(shù)通常需要兩次內(nèi)存分配:一次為對(duì)象本身,另一次為控制塊。 -
異常安全:當(dāng)使用?
new
?分配內(nèi)存并將結(jié)果傳遞給?shared_ptr
?的構(gòu)造函數(shù)時(shí),如果在參數(shù)傳遞過程中發(fā)生異常,可能會(huì)導(dǎo)致內(nèi)存泄漏。使用?make_shared
?可以避免這種風(fēng)險(xiǎn),因?yàn)?new
?和?shared_ptr
?的構(gòu)造是在一個(gè)操作中完成的。
示例
下面是使用?make_shared
?創(chuàng)建?std::shared_ptr
?的一個(gè)例子:
#include <memory>
#include <iostream>class MyClass {
public:MyClass(int a, int b) : x(a), y(b) {}void print() const { std::cout << x << " " << y << std::endl; }private:int x, y;
};int main() {auto mySharedPtr = std::make_shared<MyClass>(10, 20);mySharedPtr->print(); // 輸出: 10 20return 0;
}
注意事項(xiàng)
make_shared
?不能用于管理動(dòng)態(tài)分配的數(shù)組,因?yàn)檫@會(huì)導(dǎo)致?shared_ptr
?的析構(gòu)函數(shù)使用錯(cuò)誤的刪除器(delete
?而不是?delete[]
)。- 當(dāng)需要指定自定義的刪除器時(shí),使用?
std::allocate_shared
?而不是?make_shared
。 - 在某些情況下,
make_shared
?可能不是最佳選擇,特別是當(dāng)傳遞的參數(shù)涉及到類型轉(zhuǎn)換或需要綁定引用時(shí)。
make_shared
?是 C++ 中管理動(dòng)態(tài)內(nèi)存時(shí)非常有用的工具,可以減少代碼量并提高性能。然而,了解其使用限制和最佳實(shí)踐是編寫高效、安全代碼的關(guān)鍵。
定制刪除器(用到了包裝器)
unique和shared都有定制刪除器
因?yàn)榈讓邮莇elete,所以[ ]的釋放要實(shí)現(xiàn)一個(gè)刪除器
在shared_ptr中總代碼
template<class T>
class shared_ptr
{
public://默認(rèn)構(gòu)造shared_ptr(T* ptr=nullptr):_ptr(ptr),_count(new int(1))//這里_count是指針,要單獨(dú)開一個(gè)空間,進(jìn)行管理{}template<class D>shared_ptr(T* ptr, D del)//這里就不可以加缺省值nullptr了,因?yàn)槭菑挠业阶蟮?_ptr(ptr), _count(new int(1))//這里_count是指針,要單獨(dú)開一個(gè)空間,進(jìn)行管理,_del(del){}~shared_ptr(){(*_count)--;if ((* _count) == 0){cout << "~shared_ptr" << endl;_del(_ptr);delete _count;} }T& operator*(){return *_ptr;}T* operator->(){return _ptr;}//sp2(sp1)shared_ptr(shared_ptr<T>& ptr):_ptr(ptr._ptr),_count(ptr._count){(*_count)++;}//賦值//要考慮到前后計(jì)數(shù)要改變//如果到0了也是需要直接釋放的//如果是同一塊資源賦值可以不用處理//同一塊資源的判定條件是shared_ptr<T>& operator=(shared_ptr<T>& ptr){//同一塊資源if (_ptr == ptr._ptr)return *this;//賦值的時(shí)候,this的空間計(jì)數(shù)就少了1(*_count)--;if (*(_count) == 0){delete _ptr;delete _count;}//先增加計(jì)數(shù)也一樣然后ptr的空間資源計(jì)數(shù)就多了1//(*ptr._count)++;//賦值_ptr = ptr._ptr;_count = ptr._count;//然后ptr的空間資源計(jì)數(shù)就多了1(*_count)++;return *this;}int use_count() const{return *_count;}T* get() const{return _ptr;}
private:T* _ptr;//計(jì)數(shù)int* _count;//刪除器function<void(T*)> _del = [](T* ptr) {delete ptr; };
};
如果不是new出來的對(duì)象如何通過智能指針管理呢?其實(shí)shared_ptr設(shè)計(jì)了一個(gè)刪除器來解決這 個(gè)問題(ps:刪除器這個(gè)問題我們了解一下)
// 仿函數(shù)的刪除器
// 仿函數(shù)的刪除器template<class T>struct FreeFunc {void operator()(T* ptr){cout << "free:" << ptr << endl;free(ptr);}
};template<class T>struct DeleteArrayFunc {void operator()(T* ptr){ cout << "delete[]" << ptr << endl;delete[] ptr; }
};int main()
{FreeFunc<int> freeFunc;std::shared_ptr<int> sp1((int*)malloc(4), freeFunc);DeleteArrayFunc<int> deleteArrayFunc;std::shared_ptr<int> sp2((int*)malloc(4), deleteArrayFunc);std::shared_ptr<A> sp4(new A[10], [](A* p){delete[] p; });std::shared_ptr<FILE> sp5(fopen("test.txt", "w"), [](FILE* p)
{fclose(p); });return 0;
}
?題目
1:
weak_ptr不能單獨(dú)管理資源,必須配合shared_ptr一塊使用,解決shared_ptr中存在的 循環(huán)引用問題
RAII的實(shí)現(xiàn)方式就是在構(gòu)造函數(shù)中將資源初始化,在析構(gòu)函數(shù)中將資源清理掉
RAII方式管理資源,可以有效避免資源泄漏問題
RAII方式管理鎖,有些場(chǎng)景下可以有效避免死鎖問題
2:
A.auto_ptr智能指針是在C++98版本中已經(jīng)存在的
B.auto_ptr的多個(gè)對(duì)象之間,不能共享資源
C.auto_ptr的實(shí)現(xiàn)原理是資源的轉(zhuǎn)移
3:
C++11中提供的智能指針都只能管理單個(gè)對(duì)象的資源,沒有提供管理一段空間資源的智能指針
A.unique_ptr是C++11才正式提出的
C.unique_ptr不能使用其拷貝構(gòu)造函數(shù)
D.unique_ptr的對(duì)象之間不能相互賦值
4:
有些場(chǎng)景下shared_ptr可能會(huì)造成循環(huán)引用,必須與weak_ptr配合使用
A.shared_ptr是C++11才正式提出來的
B.shared_ptr對(duì)象之間可以共享資源
D.shared_ptr是借助引用計(jì)數(shù)的方式實(shí)現(xiàn)的
5:
weak_ptr不能單獨(dú)管理資源,因?yàn)槠浣o出的最主要的原因是配合shared_ptr解決其循環(huán) 引用問題
weak_ptr和shared_ptr都是通過引用計(jì)數(shù)實(shí)現(xiàn),但是在底層還是有區(qū)別的
weak_ptr的唯一作用就是解決shared_ptr中存在的循環(huán)引用問題,處理解決shared_ptr的循環(huán)引用問題外,別無它用