2011-07-22 136 views
13

是否有任何理由不發送參數作爲const &而不是按值,當它不會被更改並且不會進行復制?我的理解是const by value參數與沒有const(並且不會相互重載)相同,因此它仍將被複制。作爲Const參考的函數參數

我知道最好通過const &發送大對象,但我不知道這條線是在哪裏。或者如果即使很小的參數應該通過值發送,如果它們將不會被更改或複製。

注意::我試圖尋找這個,但主題是相當含糊,所以我沒有找到任何好的答案,我很抱歉如果這已被回答(發現許多問題什麼時候使用const何時使用const &但不關於價值的優勢vs const &對於不明顯的對象)。

+2

你可能會覺得這篇文章有意思:http://cpp-next.com/archive/2009/08/want-speed-pass-by-value/ – lccarrasco

+0

完全型我一直在尋找的東西,謝謝!關鍵字如此一般,我很難搜索。 –

+0

@lccarrasco:Dave Abrahams正在討論通過函數內的值來返回對象。問題是關於函數的輸入參數。在這種情況下,OP應該通過const引用傳遞本機類型以外的對象。 – Praetorian

回答

22

將只讀參數作爲常量引用傳遞並且對於任何類型的重量級類肯定是最有效的方法。但是,您可能想考慮通過複製傳遞基元類型,因爲在那裏使引用可能實際上比僅複製引起更多的成本(例如,複製只適合一個寄存器,而引用可能用一個指針等)。

此外,你可能通過std::shared_ptr和迭代器的價值,他們是爲此。

至於通過常量值,這是一個執行細節。使用這樣的:

// Declaration: 
int foo(int n, double d); // No "const"! Constness is not part of the interface. 

// Definition 
int foo(int n, const double d) // implementation detail 
{ 
    while (n--) { if (d > n) return n; } 
} 

在實現中,你可能會或可能不會選擇直接使用參數變量,並對其進行修改(如n),或者你可以選擇把它們看作是隻讀(如d ),並且適當地聲明參數。

+2

我沒有想到指針複製對原始類型來說同樣昂貴或者更差,謝謝。 –

+7

值得指出的是,如果你通過一個線程邊界引用一個引用計數句柄(比如'shared_ptr'),那麼它就變成**不可能安全地減少引用計數** - 你有*要傳遞在這種情況下的價值。 – spraff

+0

@spraff:不錯。 –

12

作爲一個經驗法則,你應該通過原語類型,如指針,intboolfloatdouble通過(非const)值,和對象類型如std::stringstd::vector和自定義類由(常數)參考。作爲這個規則的一個例外,有一些輕量級的類被專門設計用來傳遞值,比如智能指針。

通過const值傳遞一個值,例如, void foo(const double bar),是沒有意義的 - 爲什麼不應該允許foo修改其bar的副本?將參數聲明爲const在這裏沒有用處。

通過引用傳遞基元也沒什麼意義。在幕後,當一個參數通過引用傳遞時,一個指針是按值傳遞的。複製指針通常與複製基本類型(例如int)一樣昂貴,而對於大多數C++程序員來說,const int&類型的參數看起來很奇怪。

+0

如果可以的話,我會接受兩個答案! –

+3

有些人(我不在其中),他們更喜歡'const double bar'。他們說它通過覆蓋函數中參數的值來防止錯誤原因。 –

+0

只需添加到@larsmans的評論,使用'const double bar'可以防止您意外地使用'if(bar = 5)'而不是'=='。但是這樣做的代價是限制你可以用'bar'做什麼。出於某種原因,您的算法可能會要求對「bar」進行原地修改。我想這僅僅是靈活性與安全性的折衷。取決於你想信任下一位程序員多少! –