欧美一区二区三区老妇人-欧美做爰猛烈大尺度电-99久久夜色精品国产亚洲a-亚洲福利视频一区二区

聊聊 C++ 中的幾種智能指針 (上)

一:背景

我們知道 C++ 是手工管理內(nèi)存的分配和釋放,對(duì)應(yīng)的操作符就是 new/deletenew[] / delete[], 這給了程序員極大的自由度也給了我們極高的門檻,弄不好就得內(nèi)存泄露,比如下面的代碼:

成都創(chuàng)新互聯(lián)公司專業(yè)為企業(yè)提供江陰網(wǎng)站建設(shè)、江陰做網(wǎng)站、江陰網(wǎng)站設(shè)計(jì)、江陰網(wǎng)站制作等企業(yè)網(wǎng)站建設(shè)、網(wǎng)頁設(shè)計(jì)與制作、江陰企業(yè)網(wǎng)站模板建站服務(wù),10余年江陰做網(wǎng)站經(jīng)驗(yàn),不只是建網(wǎng)站,更提供有價(jià)值的思路和整體網(wǎng)絡(luò)服務(wù)。


void test() {
	int* i = new int(10);
	*i = 10;
}

int main() {
	test();
}

這段代碼因?yàn)橛昧?new 而忘了 delete,導(dǎo)致在 nt heap 上分配的 i 隨著棧地址的回收而成了一塊孤懸海外的內(nèi)存占用,所以修正后的代碼如下:


void test() {
	int* i = new int(10);
	*i = 10;

	delete i;
}

int main() {
	test();
}

但這種寫法比較麻煩,智者千慮必有一失,總會(huì)有忘記加 delete 的時(shí)候,那怎么辦呢? 大家應(yīng)該知道內(nèi)存自動(dòng)管理有兩種手段。

  1. 引用計(jì)數(shù)

代表作有 Python,PHP,還有 windows 的句柄管理。

  1. 引用跟蹤

代表作有 C#,JAVA 等一眾工程化語言。

因?yàn)?引用計(jì)數(shù) 實(shí)現(xiàn)比較簡(jiǎn)單,主要就是記錄下對(duì)象的引用次數(shù),次數(shù)為 0 則釋放,所以可完全借助 類的構(gòu)造函數(shù)析構(gòu)函數(shù)棧的自動(dòng)回收特性 弄一個(gè)簡(jiǎn)單的 引用計(jì)數(shù) ,對(duì)應(yīng)著如下四個(gè)關(guān)鍵詞。

  1. auto_ptr

  2. shared_ptr

  3. unique_ptr

  4. weak_ptr

接下來我們逐個(gè)聊一聊。

二:關(guān)鍵詞解析

1. auto_ptr

這是 C++ 最早出現(xiàn)一個(gè)的 簡(jiǎn)單引用計(jì)數(shù)法,參考代碼如下:


void test() {
	auto_ptr<int> ptr = auto_ptr<int>(new int(10));
}

int main() {
	test();
}

接下來看下匯編代碼:


	auto_ptr<int> ptr = auto_ptr<int>(new int(10));
...
00771D26  call        std::auto_ptr<int>::auto_ptr<int> (07710FAh)  
00771D2B  lea         ecx,[ebp-0D8h]  
00771D31  call        std::auto_ptr<int>::~auto_ptr<int> (0h) 

可以看到,它分別調(diào)用了 構(gòu)造函數(shù)析構(gòu)函數(shù),接下來找下 auto_ptr 這兩個(gè)函數(shù)的源碼。


class auto_ptr {

private:
	_Ty* _Myptr; // the wrapped object pointer

public:
	auto_ptr(auto_ptr_ref<_Ty> _Right) noexcept {
		_Ty* _Ptr = _Right._Ref;
		_Right._Ref = nullptr; // release old
		_Myptr = _Ptr; // reset this
	}

	~auto_ptr() noexcept {
		delete _Myptr;
	}
}

源碼一看就明白了,在構(gòu)造函數(shù)中,將 new int 的地址塞給了內(nèi)部的 _Myptr 指針,在析構(gòu)函數(shù)中對(duì) _Myptr 進(jìn)行 delete ,真好,這樣就不用整天擔(dān)心有沒有加 delete 啦。

值得注意的是,現(xiàn)在 C++ 不推薦這個(gè)了,而是建議使用新增的:shared_ptr,unique_ptr,weak_ptr, 怎么說呢? auto_ptr 有一個(gè)不好處理的問題,就是現(xiàn)實(shí)開發(fā)中會(huì)出現(xiàn)這么個(gè)場(chǎng)景,多個(gè) ptr 指向同一個(gè) 引用,如下圖:

2. auto_ptr 多引用問題

  1. 方式1:

定義三個(gè) ptr,然后包裝同一個(gè) new int 地址,參考代碼如下:


void test() {
	int* i = new int(10);

	auto_ptr<int> ptr1(i);
	auto_ptr<int> ptr2(i);
	auto_ptr<int> ptr3(i);
}

這種寫法有沒有問題呢? 肯定有問題啦,還記得 auto_ptr 的析構(gòu)是 delete 嗎? 對(duì)同一塊內(nèi)存多次 delete 會(huì)拋異常的,如下圖所示:

  1. 方式2:

既然定義三個(gè)有問題, 那就用賦值運(yùn)算符= 讓 ptr1,ptr2,ptr3 指向同一個(gè)地址是不是就可以啦? 參考代碼如下:


void test() {
	int* i = new int(10);

	auto_ptr<int> ptr1(i);
	auto_ptr<int> ptr2 = ptr1;
	auto_ptr<int> ptr3 = ptr2;
}

int main() {
	test();
}

那這段代碼有沒有問題呢? 有沒有問題得要看 = 運(yùn)算符是如何重寫的????,扒一下源碼看看。


template <class _Other>
auto_ptr& operator=(auto_ptr<_Other>& _Right) noexcept {
	reset(_Right.release());
	return *this;
}
_Ty* release() noexcept {
	_Ty* _Tmp = _Myptr;
	_Myptr = nullptr;
	return _Tmp;
}

從源碼看有一個(gè)很惡心的點(diǎn),他會(huì)將 _Right 下的 _Myptr 設(shè)為 nullptr,也就是說此時(shí)的 ptr1 報(bào)廢了,言外之意就是后續(xù)再訪問 ptr1 會(huì)拋 訪問違例

哈哈,C++里面的專業(yè)術(shù)語叫 控制權(quán)轉(zhuǎn)移

好了,本篇就說這么多吧,下一篇聊聊新增的這些關(guān)鍵詞,看看如何將 auto_ptr 更合理的分權(quán)。

本文題目:聊聊 C++ 中的幾種智能指針 (上)
本文地址:http://chinadenli.net/article4/dsoijoe.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供網(wǎng)站改版營(yíng)銷型網(wǎng)站建設(shè)、企業(yè)建站電子商務(wù)、品牌網(wǎng)站設(shè)計(jì)網(wǎng)站營(yíng)銷

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)

微信小程序開發(fā)