iT邦幫忙

2023 iThome 鐵人賽

DAY 29
0
自我挑戰組

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

[Day 29] Don't try to return a reference when you must return an object

  • 分享至 

  • xImage
  •  

前言

今天的守則接續昨天的內容,昨天提到的是盡量pass by reference,今天則是反過來提醒不要走火入魔該return object的時候也return 到reference啦~ 一起來看看吧!

收起你那大膽的想法─ 別隨便return reference

今天的守則是:

Don't try to return a reference when you must return an object

如前言所提到的,雖然傳入function的時候多半傳reference比較好,而不要pass by value,但return的時候就不是這樣了。因為你很有可能開始傳 不存在的物件的reference!

return的時候可以不要return value嗎?可以也return reference嗎?此時我們就要回頭釐清 reference究竟是什麼─ reference其實就是一個 名字,而它一定要refer到一個 存在的object。一個簡單的判斷方法:看到reference的宣告,可以想想看它的另外一個名字是什麼?因為它一定是某一個現存的 物件

那如果今天,有一個function的行為,是要return一個物件,但它目前還不存在,那要怎麼辦?首先就是要create出這個object了。

function可以創建新物件有兩種─on stack或是on heap。stack就是創建 local variable。那我們可以return local object的reference嗎?答案顯然不行,因為local obkect在function結束的時候就會被destroy掉了。這樣return的就是已經 不存在的物件的reference,結果就是undefined behavior。return local object的pointer也是如此。

那考慮一下 heap呢?Heap-based object是由new來生成的,那我們可以return一個new出來的object的reference嗎?這則會有另一個問題─ 誰來管理return出來的object的資源呢?就是delete的部分。有些情況下,這些資源有可能不會被管理到。例如這種情形:

const Rational& operator*(const Rational& lhs, const Rational& rhs)
{
    Rational *result = new Rational(lhr.n* rhs.n, lhs.d * rhs.d);
    return *result;
}

Rational w, x, y, z;
w = x * y * z;

每一個operator* 都會產生一個new的object,那應該要有兩個delete來做對應處理,但很明顯現在這樣一定會有resource leak!

以上兩種方法都行不通,而且沒有省掉constructor─畢竟你create物件的時候一樣也有用到constructor,此時可能又有一個大膽的想法─ return static object 的reference怎麼樣?每次執行的時候重複使用同一個static object,那不就可以省掉每次重新創建一個新物件的constructor了嗎?

細想下去就會發現不行了─ 這會有thread問題!且如果同時有人去call這到它,它們會return到同樣的東西!
例如以下:

const Rational& operator*(const Rational& lhs, const Rationl& rhs)
{
    static Rational result;
    result = ...
    return result;
}

Rational a, b, c, d;
if((a*b) == (c*d)) // always the same regardless of the values of a b c d!!
{
    ...
}

說了這麼多,其實就是要說明一件事─ 想從一個function裡面return reference基本上是不太合理的事。該return new object的時候就認命return 一個新物件吧!而且我們煩惱的construction, destruction耗費運算時間的問題,其實很多都會被compiler優化掉。

總結

貼心重點提醒:

  • Never return a pointer or reference to a local stack object, a reference to a heap-allocated object, or a pointer or reference to a local static object if there is a change that more than one such object will be needed.
    附註: return reference to a local static在single-threaded enviornments有合理用法

上一篇
[Day 28] Prefer pass-by-reference-to-const to pass-by-value (2)
下一篇
[Day 30] Declare data members private
系列文
Effective C++ 讀書筆記30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言