亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 編程 > C++ > 正文

C++智能指針的設計以及使用

2020-02-24 14:37:15
字體:
來源:轉載
供稿:網友

? ? ? ? 智能指針(smart pointer)是存儲指向動態分配(堆)對象指針的類,用于生存期控制,能夠確保自動正確的銷毀動態分配的對象,防止內存泄露。它的一種通用實現技術是使用引用計數(reference count)。智能指針類將一個計數器與類指向的對象相關聯,引用計數跟蹤該類有多少個對象共享同一指針。每次創建類的新對象時,初始化指針并將引用計數置為1;當對象作為另一對象的副本而創建時,拷貝構造函數拷貝指針并增加與之相應的引用計數;對一個對象進行賦值時,賦值操作符減少左操作數所指對象的引用計數(如果引用計數為減至0,則刪除對象),并增加右操作數所指對象的引用計數;調用析構函數時,構造函數減少引用計數(如果引用計數減至0,則刪除基礎對象)。
? ? ? ? 智能指針就是模擬指針動作的類。所有的智能指針都會重載 -> 和 * 操作符。智能指針還有許多其他功能,比較有用的是自動銷毀。這主要是利用棧對象的有限作用域以及臨時對象(有限作用域實現)析構函數釋放內存。當然,智能指針還不止這些,還包括復制時可以修改源對象等。智能指針根據需求不同,設計也不同(寫時復制,賦值即釋放對象擁有權限、引用計數等,控制權轉移等)。auto_ptr 即是一種常見的智能指針。
? ? ? ? 智能指針通常用類模板實現:


template
class smartpointer
{
private:
T *_ptr;
public:
smartpointer(T *p) : _ptr(p) //構造函數
{
}
T& operator *() //重載*操作符
{
return *_ptr;
}
T* operator ->() //重載->操作符
{
return _ptr;
}
~smartpointer() //析構函數
{
delete _ptr;
}
};


實現引用計數有兩種經典策略,在這里將使用其中一種,這里所用的方法中,需要定義一個單獨的具體類用以封裝引用計數和相關指針:

?

?


// 定義僅由HasPtr類使用的U_Ptr類,用于封裝使用計數和相關指針
// 這個類的所有成員都是private,我們不希望普通用戶使用U_Ptr類,所以它沒有任何public成員
// 將HasPtr類設置為友元,使其成員可以訪問U_Ptr的成員
class U_Ptr
{
friend class HasPtr;
int *ip;
size_t use;
U_Ptr(int *p) : ip(p) , use(1)
{
cout }
~U_Ptr()
{
delete ip;
cout }
};


? ? ? ? HasPtr類需要一個析構函數來刪除指針。但是,析構函數不能無條件的刪除指針?!?br>? ? ? ? 條件就是引用計數。如果該對象被兩個指針所指,那么刪除其中一個指針,并不會調用該指針的析構函數,因為此時還有另外一個指針指向該對象??磥恚悄苤羔樦饕穷A防不當的析構行為,防止出現懸垂指針。

? ? ? ? 如上圖所示,HasPtr就是智能指針,U_Ptr為計數器;里面有個變量use和指針ip,use記錄了*ip對象被多少個HasPtr對象所指。假設現在又兩個HasPtr對象p1、p2指向了U_Ptr,那么現在我delete? p1,use變量將自減1,? U_Ptr不會析構,那么U_Ptr指向的對象也不會析構,那么p2仍然指向了原來的對象,而不會變成一個懸空指針。當delete p2的時候,use變量將自減1,為0。此時,U_Ptr對象進行析構,那么U_Ptr指向的對象也進行析構,保證不會出現內存泄露。?
? ? ? ? 包含指針的類需要特別注意復制控制,原因是復制指針時只復制指針中的地址,而不會復制指針指向的對象。
? ? ? ? 大多數C++++類用三種方法之一管理指針成員
? ? ? ? (1)不管指針成員。復制時只復制指針,不復制指針指向的對象。當其中一個指針把其指向的對象的空間釋放后,其它指針都成了懸浮指針。這是一種極端
? ? ? ? (2)當復制的時候,即復制指針,也復制指針指向的對象。這樣可能造成空間的浪費。因為指針指向的對象的復制不一定是必要的。
? ? ? ? (3) 第三種就是一種折中的方式。利用一個輔助類來管理指針的復制。原來的類中有一個指針指向輔助類,輔助類的數據成員是一個計數器和一個指針(指向原來的)(此為本次智能指針實現方式)。
? ? ? ? 其實,智能指針的引用計數類似于java的垃圾回收機制:java的垃圾的判定很簡答,如果一個對象沒有引用所指,那么該對象為垃圾。系統就可以回收了。
? ? ? ? HasPtr 智能指針的聲明如下,保存一個指向U_Ptr對象的指針,U_Ptr對象指向實際的int基礎對象,代碼如下:

?

?


#include
using namespace std;

// 定義僅由HasPtr類使用的U_Ptr類,用于封裝使用計數和相關指針
// 這個類的所有成員都是private,我們不希望普通用戶使用U_Ptr類,所以它沒有任何public成員
// 將HasPtr類設置為友元,使其成員可以訪問U_Ptr的成員
class U_Ptr
{
?? ?friend class HasPtr;
?? ?int *ip;
?? ?size_t use;
?? ?U_Ptr(int *p) : ip(p) , use(1)
?? ?{
?? ??? ?cout ?? ?}
?? ?~U_Ptr()
?? ?{
?? ??? ?delete ip;
?? ??? ?cout ?? ?}
};

class HasPtr
{
public:
?? ?// 構造函數:p是指向已經動態創建的int對象指針
?? ?HasPtr(int *p, int i) : ptr(new U_Ptr(p)) , val(i)
?? ?{
?? ??? ?cout use ?? ?}

?? ?// 復制構造函數:復制成員并將使用計數加1
?? ?HasPtr(const HasPtr& orig) : ptr(orig.ptr) , val(orig.val)
?? ?{
?? ??? ?++ptr->use;
?? ??? ?cout use ?? ?}

?? ?// 賦值操作符
?? ?HasPtr& operator=(const HasPtr&);

?? ?// 析構函數:如果計數為0,則刪除U_Ptr對象
?? ?~HasPtr()
?? ?{
?? ??? ?cout use ?? ??? ?if (--ptr->use == 0)
?? ??? ??? ?delete ptr;
?? ?}

?? ?// 獲取數據成員
?? ?int *get_ptr() const
?? ?{
?? ??? ?return ptr->ip;
?? ?}
?? ?int get_int() const
?? ?{
?? ??? ?return val;
?? ?}

?? ?// 修改數據成員
?? ?void set_ptr(int *p) const
?? ?{
?? ??? ?ptr->ip = p;
?? ?}
?? ?void set_int(int i)
?? ?{
?? ??? ?val = i;
?? ?}

?? ?// 返回或修改基礎int對象
?? ?int get_ptr_val() const
?? ?{
?? ??? ?return *ptr->ip;
?? ?}
?? ?void set_ptr_val(int i)
?? ?{
?? ??? ?*ptr->ip = i;
?? ?}
private:
?? ?U_Ptr *ptr;?? //指向使用計數類U_Ptr
?? ?int val;
};
HasPtr& HasPtr::operator = (const HasPtr &rhs)? //注意,這里賦值操作符在減少做操作數的使用計數之前使rhs的使用技術加1,從而防止自我賦值
{
?? ?// 增加右操作數中的使用計數
?? ?++rhs.ptr->use;
?? ?// 將左操作數對象的使用計數減1,若該對象的使用計數減至0,則刪除該對象
?? ?if (--ptr->use == 0)
?? ??? ?delete ptr;
?? ?ptr = rhs.ptr;?? // 復制U_Ptr指針
?? ?val = rhs.val;?? // 復制int成員
?? ?return *this;
}

int main(void)
{
?? ?int *pi = new int(42);
?? ?HasPtr *hpa = new HasPtr(pi, 100);??? // 構造函數
?? ?HasPtr *hpb = new HasPtr(*hpa);???? // 拷貝構造函數
?? ?HasPtr *hpc = new HasPtr(*hpb);???? // 拷貝構造函數
?? ?HasPtr hpd = *hpa;???? // 拷貝構造函數

?? ?cout get_ptr_val() get_ptr_val() ?? ?hpc->set_ptr_val(10000);
?? ?cout get_ptr_val() get_ptr_val() ?? ?hpd.set_ptr_val(10);
?? ?cout get_ptr_val() get_ptr_val() ?? ?delete hpa;
?? ?delete hpb;
?? ?delete hpc;
?? ?cout ?? ?return 0;
}


這里的賦值操作符比較麻煩,且讓我用圖表分析一番:
假設現在又兩個智能指針p1、 p2,一個指向內容為42的內存,一個指向內容為100的內存,如下圖:

現在,我要做賦值操作,p2 = p1。對比著上面的

?

?

?


HasPtr& operator=(const HasPtr&); // 賦值操作符

?

此時,rhs就是p1,首先將p1指向的ptr的use加1,

?

?

++rhs.ptr->use; // 增加右操作數中的使用計數

?

然后,做:

?

?

if (--ptr->use == 0)
delete ptr;

?

因為,原先p2指向的對象現在p2不在指向,那么該對象就少了一個指針去指,所以,use做自減1;
此時,條件成立。因為u2的use為1。那么,運行U_Ptr的析構函數,而在U_Ptr的析構函數中,做了delete ip操作,所以釋放了內存,不會有內存泄露的問題。
接下來的操作很自然,無需多言:

?

?

ptr = rhs.ptr; // 復制U_Ptr指針
val = rhs.val; // 復制int成員
return *this;

?

做完賦值操作后,那么就成為如下圖所示了。紅色標注的就是變化的部分:

而還要注意的是,重載賦值操作符的時候,一定要注意的是,檢查自我賦值的情況。
如圖所示:

此時,做p1 = p1的操作。那么,首先u1.use自增1,為2;然后,u1.use自減1,為1。那么就不會執行delete操作,剩下的操作都可以順利進行。按《C++ primer》說法,“這個賦值操作符在減少左操作數的使用計數之前使rhs的使用計數加1,從而防止自身賦值”。哎,反正我是那樣理解的。當然,賦值操作符函數中一來就可以按常規那樣:

?

?

if(this == &rhs)
return *this;

?

運行結果如下圖:

以上就是C++智能指針的設計以及使用的全部內容,如果有疑問大家可以留言交流。,與君共勉,一起學習。

?

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
成人av在线天堂| 亚洲精品成人久久久| 81精品国产乱码久久久久久| 国产女人18毛片水18精品| 国产精品视频精品视频| 国产偷亚洲偷欧美偷精品| 91在线视频精品| 日韩电影在线观看中文字幕| 日本欧美黄网站| 亚洲美女精品久久| 亚洲欧美在线x视频| 5278欧美一区二区三区| 日韩欧美中文字幕在线观看| 日日骚久久av| 欧美丰满老妇厨房牲生活| 国产精品99久久久久久www| 欧美午夜影院在线视频| 亚洲福利视频久久| 岛国av一区二区三区| 欧美国产日韩二区| 国产精品旅馆在线| 欧美国产欧美亚洲国产日韩mv天天看完整| 福利视频导航一区| 久久精彩免费视频| 欧美一级淫片aaaaaaa视频| 7777kkkk成人观看| 亚洲午夜女主播在线直播| 91香蕉电影院| 欧美重口另类videos人妖| 亚洲一区二区三区四区视频| 欧美日韩亚洲一区二| 亚洲18私人小影院| 亚洲精品国产欧美| 国产欧美一区二区白浆黑人| 亚洲一区免费网站| 海角国产乱辈乱精品视频| 久操成人在线视频| 亚洲一区二区三区xxx视频| 亚洲性夜色噜噜噜7777| 97婷婷涩涩精品一区| 日韩男女性生活视频| 中文字幕少妇一区二区三区| 国产精品香蕉在线观看| 少妇精69xxtheporn| 欧美成人精品在线| 日本欧美国产在线| 中文字幕视频一区二区在线有码| 日韩欧美第一页| 最近2019中文字幕一页二页| 色婷婷综合成人| 九九热这里只有精品免费看| 国产91精品久久久久久| 裸体女人亚洲精品一区| 国产精品极品美女在线观看免费| 欧美性色xo影院| 欧美日韩国产激情| 亚洲无av在线中文字幕| 日韩免费观看视频| 日韩中文字幕在线免费观看| 久久久久一本一区二区青青蜜月| 色噜噜国产精品视频一区二区| 91精品国产综合久久香蕉| 成人免费看吃奶视频网站| 91国产一区在线| 在线电影中文日韩| 欧美综合在线观看| 久久亚洲精品网站| 精品亚洲一区二区| 欧美又大粗又爽又黄大片视频| 国产精品成人品| 久久九九免费视频| 国产精品电影网站| 国产精品视频久久久久| 最近中文字幕2019免费| 国产精品一区=区| 日韩电影在线观看永久视频免费网站| 欧美丝袜一区二区| 亚洲自拍在线观看| 国产精品96久久久久久| 91免费版网站入口| 欧美视频专区一二在线观看| 国产精品露脸av在线| 久久久99久久精品女同性| 成人激情电影一区二区| 国产精品∨欧美精品v日韩精品| 欧美精品在线视频观看| 北条麻妃久久精品| 亲子乱一区二区三区电影| 伦伦影院午夜日韩欧美限制| 亚洲国产成人久久| 日韩精品亚洲精品| 日韩av在线免费看| 久久影视电视剧免费网站清宫辞电视| 欧美精品18videos性欧| 在线播放日韩专区| 国内成人精品视频| 91久久精品久久国产性色也91| 国产成人精品av| 精品久久香蕉国产线看观看亚洲| 欧洲美女免费图片一区| 97视频在线观看成人| 亚洲综合在线做性| 欧美精品videosex牲欧美| 午夜精品久久久久久久白皮肤| 精品国产老师黑色丝袜高跟鞋| 欧美日韩午夜视频在线观看| 亚洲一区av在线播放| 55夜色66夜色国产精品视频| 国产综合久久久久| 亚洲精品一区二区网址| 伊人久久综合97精品| 日韩中文字幕在线看| 日韩中文字幕在线免费观看| 国产97在线|日韩| 欧美国产日韩视频| 日韩av免费在线观看| 日韩免费看的电影电视剧大全| 亚洲欧美中文字幕在线一区| 色先锋久久影院av| 正在播放欧美一区| 亚洲欧美国内爽妇网| 久久福利网址导航| 日韩精品免费在线观看| 欧美日韩国产999| 欧美另类在线播放| 欧美高清在线观看| 永久免费毛片在线播放不卡| 欧美激情在线狂野欧美精品| 国产一区红桃视频| 亚洲xxxxx性| 国产精品免费在线免费| 一本一本久久a久久精品综合小说| 日本不卡高字幕在线2019| 精品少妇v888av| 日韩欧美999| 欧美激情a∨在线视频播放| 日韩一区二区av| 久久精品人人做人人爽| 91精品久久久久久综合乱菊| 亚洲精品自产拍| 欧美高清在线观看| 91午夜理伦私人影院| 精品一区二区三区三区| 欧美精品中文字幕一区| 69影院欧美专区视频| 亚洲精品自拍偷拍| 尤物yw午夜国产精品视频明星| 国产精品高清免费在线观看| 精品伊人久久97| 最新国产成人av网站网址麻豆| 久久成人免费视频| 久久精品国产亚洲| 欧美激情视频一区二区三区不卡| 欧美肥臀大乳一区二区免费视频| 欧美中文在线字幕| 久久久久久久999精品视频| 北条麻妃久久精品| 日本精品免费观看| 97福利一区二区| 国模精品系列视频| 色综合久久中文字幕综合网小说| 亚洲欧美激情在线视频| 中文字幕在线精品| 色视频www在线播放国产成人|