iT邦幫忙

2023 iThome 鐵人賽

DAY 22
0
自我挑戰組

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

[Day 22] Use the same form in corresponding uses of new and delete

  • 分享至 

  • xImage
  •  

前言

今天介紹的是資源管理中,delete要注意是否需要delete [],一起來看看吧!

是不是array? new與delete請一致

今天的守則是:

Use the same form in corresponding uses of new and delete

最開頭書中提供了一個例子:

std::string *stringArray = new std::string[100];
...
delete stringArray;

以上會有什麼問題呢?
結果會是undefined的,可以確信的一點是至少有99個被stringArray指向的string object沒有被適當destroy,因為delete stringArray,compiler只知道要去刪除一個stringArray object。

當我們用new的時候,會做兩件事: 1. 分配memory;2. 該memory的相應constructors動起來;而delete一樣會做兩件事: 1. memory對應的destructors被call起來;2. 釋放memory

而其中有個重點就是,delete時被delete的pointer指向的是 一個單一物件 or 物件array?這很重要因為兩者的memory layout是不同的。通常array的memory會包含array的size,讓delete的時候可以知道要call多少destructor,而單一物件的memory就沒這東西。

而當我們對pointer使用delete的時候,delete要怎麼知道他要delete的memory是長什麼樣子呢?就只能依靠我們用[]與否來告訴它了。有了[],delete就會認為要刪除的pointer指向的對象是array,就會知道要去讀例如array size,來知道要call哪些destructor─否則,delete一律當成要刪除的pointer就是一個single object。

正確用法就像這樣:

std::string *stringPtr1 = new std::string;
std::string *stringPtr2 = new std::string[100];
...
delete stringPtr1;
delete [] stringPtr2;

相對於最開頭的例子,如果這樣又會發生什麼事呢?

delete [] stringPtr1;

一樣,undefined,如上面所言,如果compiler存array的memory方式是先放array size,後面是那些物件,那delete操作就很可能誤將物件的memory解讀為array size,進而call了一堆不該call的destructor。

所以呼應今天的守則,規則非常簡單─如果在new裡面有用[],那就要相對應的delete [];反之亦然

class與typedef多注意

這在有多種constructor的class中特別需要注意,因為每個constructor都應該用一樣的new方式,例如都是single object,or都是array,這樣destructor裡面才能正確地destroy掉各種constructor new出來的物件!

還有一個地方也特別需要注意的─typedef。typedef應該特別註明使用到這類型的object時,應採用哪種delete方式,以符合它的type,例如以下:

typedef std::string AddressLines[4];

std::string *pal = new AddressLines;
delete pal; // undefined
delete [] pal; // fine

因為AddressLines是array,所以它對應的delete應該也要是array。

而要避開這種潛在陷阱的辦法就是直接避開在typedef使用array types。這很簡單,就如之前有提過的([Day 19] Use objects to manage resources),因為C++ library裡面就有stringvector這種templates,實在沒什麼需要自行動態分配array的地方。

總結

貼心重點提醒:

  • If you use [] in a new expression, you must use [] in the corresponding delete expression. If you don't use [] in a new expression, you mustn't use [] in the corresponding delete expression.

不知道為什麼寫的這麼拗口XD 很簡單就是new有用到[],記得delete也要delete [];反之如果沒有,就不要亂delete []


上一篇
[Day 21] Provide access to raw resources in resource-managing classes
下一篇
[Day 23] Store new objects in smart pointers in standalone statements
系列文
Effective C++ 讀書筆記30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言