iT邦幫忙

2023 iThome 鐵人賽

DAY 28
0
自我挑戰組

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

[Day 28] Prefer pass-by-reference-to-const to pass-by-value (2)

  • 分享至 

  • xImage
  •  

前言

昨天介紹了盡量pass by reference by const這條守則,並說明它可以bypass掉昂貴的construct, destruct操作,也可以避免slicing的問題,今天我們就接續下去,看一下sliced-off問題的實例,以及什麼時候反而應該選用"pass by value"。

Slicing problem

我們直接來看看pass by value會遇到的sliced-off問題實例~
假設現在我們有個class:

class Window
{
public:
    ...
    std::string name() const;
    virtual void display() const;
};

class WindowWithScrollBars: public Window
{
public:
    ...
    virtual void display() const;
}

可以看到其中displayvirtual的,並且在derived class中有override它,所以我們期望它的行為會依據是Window or WindowWithScrollBars而不同。而如果我們這樣將這個object傳入function來處理:

void printNameAndDisplay(Window w)
{
    std::cout << w.name();
    w.display();
}

WindowWithScrollBars wwsb;
printNameAndDisplay(wwsb);

後果就是在printNameAndDisplay裡面,w會被initialize為Window物件,而這個function裡面的行為就會走Window::display那一路,永遠不會走到WindowWithScrollBars::display

而如果改用 pass by reference to const 的形式來傳:

void printNameAndDisplay(const Window& w)
{
    std::cout << w.name();
    w.display();
}

w就會依照 實際傳入 的物件來行為了!例如此時它就會走WindowWithScrollBars::display這一路。

Built-in type除外

在C++ compiler的實作中,referencepointer的運作方式很像,而"pass by reference"也實際上就像是"pass by pointer"。

而如果現在function中需要的參數是 built-in typepass by value通常會更有效率!!因為他們在被設計的時候就是被以 "pass by value" 去考量的。而 iteratorsSTL中的function object 也適合"pass by value",因為他們的實作則是被設計為能有效地被copy,且也不會有slicing problem的問題。

還有一個要釐清的概念,就是 不是所有"小"的物件pass-by-value就沒差。有些user-defined物件也不大,但不代表它construct, destruct的代價就比較小。例如有些物件中含有pointers,那copy那些物件就包含要copy所有它指向的物件!這個操作代價就很高。

退一步說,即使copy constructor的代價不大,還是有可能會有 performance issues。有些compiler對built-in type跟user-defined type的處理不同,例如就算它跟built-in type包含的東西都相同,但compiler就是不願意把它跟built-in type一樣處理,堅持要用pointers來處理。

還有另一個user-defined type無論大小,最好採用"pass by reference"的原因是,即使現在user-defined type真的很單純代價不大,但user-defined type是可能動態改變的,有可能之後被一直擴充,變得越來越大。

總結來說,大部分情況下本條守則都是成立的,只有 built-in typeSTL interator跟function obejct types除外,此外還是盡量使用 "pass by reference to const" 吧!

總結

貼心重點提醒:

  • Prefer pass-by-reference-to-const over pass-by-value. It's typically more efficient and it avoids the slicing problem.
  • The rule doesn't apply to built-in types and STL iterator and function object types. For them, pass-by-value is usually appropriate.

在剛開始學寫程式時感覺比較少有提過這條守則相關的概念,感覺可以翻轉一下,盡量都用refernce來傳遞~ 當然也別矯枉過正─built-in type直接傳就好。


上一篇
[Day 27] Prefer pass-by-reference-to-const to pass-by-value (1)
下一篇
[Day 29] Don't try to return a reference when you must return an object
系列文
Effective C++ 讀書筆記30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言