<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
我們知道 C++ 是手工管理記憶體的分配和釋放,對應的操作符就是 new/delete
和 new[] / delete[]
, 這給了程式設計師極大的自由度也給了我們極高的門檻,弄不好就得記憶體洩露,比如下面的程式碼:
void test() { int* i = new int(10); *i = 10; } int main() { test(); }
這段程式碼因為用了 new 而忘了 delete,導致在 nt heap
上分配的 i 隨著棧地址的回收而成了一塊孤懸海外的記憶體佔用,所以修正後的程式碼如下:
void test() { int* i = new int(10); *i = 10; delete i; } int main() { test(); }
但這種寫法比較麻煩,智者千慮必有一失,總會有忘記加 delete 的時候,那怎麼辦呢? 大家應該知道記憶體自動管理有兩種手段。
1.參照計數
代表作有 Python,PHP,還有 windows 的控制程式碼管理。
2.參照跟蹤
代表作有 C#,JAVA 等一眾工程化語言。
因為 參照計數 實現比較簡單,主要就是記錄下物件的參照次數,次數為 0 則釋放,所以可完全藉助 類別建構函式解構函式 和 棧的自動回收特性 弄一個簡單的 參照計數 ,對應著如下四個關鍵詞。
接下來我們逐個聊一聊。
這是 C++ 最早出現一個的 簡單參照計數法,參考程式碼如下:
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> (0771159h)
可以看到,它分別呼叫了 建構函式 和 解構函式,接下來找下 auto_ptr 這兩個函數的原始碼。
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; } }
原始碼一看就明白了,在建構函式中,將 new int 的地址塞給了內部的 _Myptr
指標,在解構函式中對 _Myptr
進行 delete
,真好,這樣就不用整天擔心有沒有加 delete 啦。
值得注意的是,現在 C++ 不推薦這個了,而是建議使用新增的:shared_ptr,unique_ptr,weak_ptr
, 怎麼說呢? auto_ptr 有一個不好處理的問題,就是現實開發中會出現這麼個場景,多個 ptr 指向同一個 參照,如下圖:
方式1:
定義三個 ptr,然後包裝同一個 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 的解構是 delete 嗎? 對同一塊記憶體多次 delete 會拋異常的,如下圖所示:
方式2:
既然定義三個有問題, 那就用賦值運運算元=
讓 ptr1,ptr2,ptr3 指向同一個地址是不是就可以啦? 參考程式碼如下:
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(); }
那這段程式碼有沒有問題呢? 有沒有問題得要看 =
運運算元是如何重寫的,扒一下原始碼看看。
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; }
從原始碼看有一個很噁心的點,他會將 _Right
下的 _Myptr
設為 nullptr,也就是說此時的 ptr1 報廢了,言外之意就是後續再存取 ptr1 會拋 存取違例。
哈哈,C++裡面的專業術語叫 控制權轉移。
以上就是一起聊聊C++中的智慧指標的詳細內容,更多關於C++智慧指標的資料請關注it145.com其它相關文章!
相關文章
<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
综合看Anker超能充系列的性价比很高,并且与不仅和iPhone12/苹果<em>Mac</em>Book很配,而且适合多设备充电需求的日常使用或差旅场景,不管是安卓还是Switch同样也能用得上它,希望这次分享能给准备购入充电器的小伙伴们有所
2021-06-01 09:31:42
除了L4WUDU与吴亦凡已经多次共事,成为了明面上的厂牌成员,吴亦凡还曾带领20XXCLUB全队参加2020年的一场音乐节,这也是20XXCLUB首次全员合照,王嗣尧Turbo、陈彦希Regi、<em>Mac</em> Ova Seas、林渝植等人全部出场。然而让
2021-06-01 09:31:34
目前应用IPFS的机构:1 谷歌<em>浏览器</em>支持IPFS分布式协议 2 万维网 (历史档案博物馆)数据库 3 火狐<em>浏览器</em>支持 IPFS分布式协议 4 EOS 等数字货币数据存储 5 美国国会图书馆,历史资料永久保存在 IPFS 6 加
2021-06-01 09:31:24
开拓者的车机是兼容苹果和<em>安卓</em>,虽然我不怎么用,但确实兼顾了我家人的很多需求:副驾的门板还配有解锁开关,有的时候老婆开车,下车的时候偶尔会忘记解锁,我在副驾驶可以自己开门:第二排设计很好,不仅配置了一个很大的
2021-06-01 09:30:48
不仅是<em>安卓</em>手机,苹果手机的降价力度也是前所未有了,iPhone12也“跳水价”了,发布价是6799元,如今已经跌至5308元,降价幅度超过1400元,最新定价确认了。iPhone12是苹果首款5G手机,同时也是全球首款5nm芯片的智能机,它
2021-06-01 09:30:45