iT邦幫忙

2023 iThome 鐵人賽

DAY 23
0
自我挑戰組

Effective C++ 讀書筆記系列 第 23

[Day 23] Store new objects in smart pointers in standalone statements

  • 分享至 

  • xImage
  •  

前言

不知不覺就直接來到第三章最後一個守則了!今天的守則雖然簡單,但乍看之下不會直接想到原因,書中詳盡解釋了其中的道理,讓人有輕鬆掌握到知識的感覺XD 就來看看吧~

在同一個statement不要做存入smart pointer以外的事!

今天的守則是:

Store newed objects in smart pointers in standalone statements

假設今天的情境是我們有下面兩個function:

int priority();
void processWidget(std::shared_ptr<Widget> pw, int priority);

深受前幾天守則宣導的我們,自然地知道pointer要採用物件來管理比較好!於是掏出最實用的RAII─shared_ptr~來管理Widget。那現在我們要call processWidget這個function,要怎麼call呢?

首先初級版錯誤示範:

prcoessWidget(new Widget, prioirty()); // error

原因:這個function接受的input是shared_ptr,而raw pointer要轉成shared_ptr必須是explicit,沒有implicit的轉法。

以下是能動的版本:

processWidget(std::shared_ptr<Widget>(new Widget), priority());

一切看起來都很好,大家都有用object來管理資源,但其實這是陷阱!以上這個call法有可能會leak resource
WHY
且看大師娓娓道來:
首先,compiler要call processWidget之前,會先計算傳入的arguments
第一個引數std::shared_ptr<Widget>(new Widget)包含了兩部分:

  1. new Widget的執行
  2. call shard_ptr的constructor

外加第二個引數priorty()是一個function call:
3. call priority

而C++的特性是對執行順序的自由度頗高,沒有像Java或C#對參數的計算有明確順序。這邊有必定前後關係的只有1需要在2前面,因為2需要1的結果。然而3這項,就不一定會是在一開始,或1跟2中間,或最後執行。如果compiler最後決定在中間call(有可能為了產生比較有效率的code所以這樣排),那順序就變成這樣:

  1. new Widget的執行
  2. call priority
  3. call shared_ptr的constructor

可以看到new Widget跟轉成shared_ptr被拆開啦!這代表什麼?代表違反了RAII!(忘記RAII是什麼嗎?可以再看一遍─)

如果priority()中途出了什麼差錯,那3就不會被執行,它就沒被存到shared_ptr裡面惹,那這個Widgetpointer就有leak的風險!(沒有被確保會被delete)

那解決方法也很簡單,保證不要讓別人插斷就行了,移除掉3這個不確定因子,就切合主題─請單獨call 1.2這兩件事!
像是這樣:

std::shared_ptr<Widget> pw(new Widget);
processWidget(pw, prioirty());

大功告成!

總結

貼心重點提醒:

  • Store newed objects in smart pointers in standalone statements. Failure to do this can lead to subtle resource leaks when exceptions are thrown.

第三章就到此結束啦!讓我們期待第四章─Designs and declarations的精采內容,當然也可以回去複習一下到此為止的17條守則們([Day 1] 前言)~


上一篇
[Day 22] Use the same form in corresponding uses of new and delete
下一篇
[Day 24] Make interfaces easy to use correctly and hard to use incorrectly (1)
系列文
Effective C++ 讀書筆記30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言