2013-07-13 33 views
17

我剛纔所讀經典書「有效的C++,第3版」,並在第20項筆者的結論是,內置類型,STL的迭代器和函數對象種類較多,適合傳遞價值。我可以很好理解內建和迭代器類型的原因,但爲什麼要函數對象被傳遞由值,因爲我們知道這是無論如何類類型?爲什麼函數對象應該是通過按值

+2

+1看了C++有效 – Borgleader

+0

函數對象應該很少有多大的開銷。 – chris

+0

至少,現在有更多的邏輯(所有對象,一般)都有移動語義。 –

回答

18

在典型的情況下,一個功能對象將有很少或(更通常)沒有持久狀態。在這種情況下,通過價值傳遞可能不需要實際傳遞任何東西 - 傳遞的「價值」基本上只是「這是對象」的佔位符。

由於許多函數對象中的代碼量很少,導致進一步優化:編譯器通常很容易擴展函數對象的內聯代碼,因此沒有參數傳遞,並且沒有函數調用參與其中。

編譯器可以能夠當你通過指針或引用,而不是做同樣的,但它不是那麼容易 - 很多比較常見的,你會與對象最終被創建的,其地址傳遞,然後通過該指針調用該對象的函數調用操作符。

編輯:這可能也是值得一提的是,同樣適用於lambda表達式,因爲他們真的只是功能僞裝對象。你不知道類的名字,但是他們在緊鄰的作用域中創建一個類,它重載了函數調用操作符,當你「調用」lambda時被調用。 [感謝@馬克西亞。]

+0

感謝您的解釋,「內聯優化」部分讓我印象深刻。 – JavaBeta

+1

我的工作經驗表明,廣泛使用'boost :: bind'會導致複製的代價很高的函數對象。這似乎成倍增加綁定深度(結合具有結合內部等回調回調) –

1

從有效的STL(因爲你看起來很喜歡斯科特·邁耶斯)第38項設計仿函數類用於傳遞值

「在C和C++中,函數指針都是按值傳遞的,STL函數對象是在函數指針之後建模的,所以STL中的約定是,函數對象也是在函數傳遞時通過值傳遞的。 「編輯器可以做一些優化,比如內聯代碼以避免函數調用(你必須將你的函數標記爲內聯),這有一些好處和一些暗示,像@Jerry Coffin說的。這種情況的一個很好的例子是qsort vs std :: sort性能比較,其中std :: sort使用內聯函數的性能比qsort大很多,你可以在有效的STL中找到更多關於這方面的信息,這在廣泛討論並在幾個章節。

這也有一些暗示,因爲函數對象是通過值並返回的,所以您必須確保您的對象具有定義良好的複製機制,體積小(否則可能會變得昂貴),並且是單形的(因爲按值傳遞多態對象可能會導致對象切片)。

+0

邁爾斯的有效串聯是在中國很受歡迎:-)。另外,感謝std :: sort和std :: qsort之間的區別。 – JavaBeta

4

#1原因按值傳遞函數對象是因爲標準庫需要函數對象傳遞給它的算法,可拷貝。 C++ 11§25.1/ 10:

[注:除非另有規定,即採取函數對象作爲參數被允許的算法複製 那些功能自由對象。對他們來說,程序員對象的身份是很重要的應該考慮使用一個指向noncopied實施對象,如reference_wrapper<T>(20.8.3), 或某些等效解決方案 包裝類。 - 注意]

其他答案做了很好的解釋理由。

相關問題