C++中傳值方式傳參與引用常量傳參的使用規則

揭開 C++ 編譯器的面紗,你將會發現引用通常情況下是以指針的形式實現的,所以通過引用傳遞通常意味着實際上是在傳遞一個指針。因此,如果傳遞一個內建數據類型的對象(比如 int ),傳值會比傳遞引用更爲高效。那麼,對於內建數據類型,當你在傳值和傳遞常量引用之間徘徊時,傳值方式不失爲一個更好的選擇。迭代器 和 STL 中的函數對象都是如此,這是因爲它們設計的初衷就是更適於傳值,這是 C++ 的慣例。實現迭代器和函數對象的人員有責任考慮複製時的效率問題和截斷問題。(這就是一個“使用哪種規則,取決於當前使用哪一部份的 C++ ”,參見第 1 條)

內建數據類型體積較小,所以一些人得出這樣的結論:所有體積較小的類型都適合使用傳值,即使它們是用戶自定義的。這是一個不可靠的推理。僅僅通過一個對象體積小並不能判定調用它的拷貝構造函數的代價就很低。許多對象——包括大多數 STL 容器——其中僅僅包含一個指針和很少量的其它內容,但是複製這樣的對象的同時,它所指向的所有內容都需要複製。這將會是一件十分昂貴的事情。

即使體積較小的對象的拷貝構造函數不會帶來昂貴的開銷,它也會引入性能問題。一些編譯器對內建數據類型和用戶自定義數據類型是分別對待的,即使它們的原始表示方式完全相同。比如說一些編譯器很樂意將一個單純的 double 值放入寄存器中,這是語言的常規,但將僅包含一個 double 值的對象放入寄存器時,編譯器就會報錯了。當你遇到這種事情時,你可以使用引用傳遞這類對象,因爲編譯器此時一定會將指針(引用的具體實現)放入寄存器中。

小型用戶自定義數據類型不適用於傳值方式還有一個理由,那就是:作爲用戶自定義類型,它們的大小並不是固定的。現在很小的類型在未來的版本中可能會變得很大,這是因爲它的內部實現方式可能會改變。即使是你更改了 C++ 語言的具體實現都可能會影響到類型的大小。比如,在我編寫上面的示例的時候,一些對標準庫中 string 實現的大小竟然達到了另一些的七倍。

總體上講,只有內建數據類型、 STL 迭代器和函數對象類型適用於傳值方式。對於所有其它的類型,都應該遵循本條款中的建議:使用引用常量傳參,而不是傳值。

牢記在心

  • 儘量使用引用常量傳參,而不是傳值方式。因爲傳引用更高效,而且可以避免“截斷問題”。
  • 對於內建數據類型、 STL 迭代和函數對象類型,這一規則就不適用了,對它們來說通常傳值方式更實用。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章