2011-02-02 27 views
6

我可以寫一個模板函數這樣模板按值傳遞或const引用或...?

template<class T> void f(T x) {...} 

或這樣

template<class T> void f(T const& x) {...} 

我想,第二個選項可以更優化,因爲它明確地避免了複製,但我懷疑它可以對於某些特定類型T(例如仿函數?)也失敗。 那麼,什麼時候應該使用第一個選項,何時使用第二個選項?也有這boost::call_traits<T>::param_typeboost::reference_wrapper是在我的previous question的答案,但人們不使用它們到處都是,是嗎?這是否有一個經驗法則?謝謝。

+1

冒着看起來很愚蠢的風險,我必須問:一個函子怎麼會失敗? – Beta 2011-02-02 16:22:06

+0

@貝塔:這是一個隨機猜測。如果有人能夠解釋在哪些情況下它實際上可能會失敗,我會感興趣。 – 2011-02-02 16:23:40

+0

你試圖實現什麼?它取決於`f`中的內部代碼。 – 2011-02-02 16:39:44

回答

11

有沒有經驗法則呢?

關於何時使用通過引用與通過值的通用規則適用。

如果您希望T始終是一個數值類型或複製非常便宜的類型,那麼您可以通過值獲取參數。如果你打算在函數中將參數拷貝到本地變量中,那麼你應該把它的值作爲help the compiler elide copies that don't really need to be made.

否則,請參考參數。在複製便宜的類型的情況下,它可能更昂貴,但對於其他類型,它將更快。如果你發現這是一個性能熱點,你可以爲不同類型的參數重載函數,併爲它們中的每一個做正確的事情。

0

除了詹姆斯·McNellis寫的,我只是想補充一點,你可以專注你的引用類型的模板(for example like this

6

我懷疑它也可能會因某些特定類型的

通過引用傳遞給const是,「從來沒有」失敗的唯一傳遞機制。它不會對T提出任何要求,它接受左值和右值作爲參數,並允許隱式轉換。

1

不可喚醒死人,但前往一個類似的問題,這裏的一些示例代碼,演示瞭如何使用C++ 11S型特徵來推斷是否參數應通過值或引用傳遞:

#include <iostream> 
#include <type_traits> 

template<typename key_type> 
class example 
{ 
    using parameter_type = typename std::conditional<std::is_fundamental<key_type>::value, key_type, key_type&>::type; 

public: 
    void function(parameter_type param) 
    { 
     if (std::is_reference<parameter_type>::value) 
     { 
      std::cout << "passed by reference" << std::endl; 
     } else { 
      std::cout << "passed by value" << std::endl; 
     } 
    } 
}; 

struct non_fundamental_type 
{ 
    int one; 
    char * two; 
}; 

int main() 
{ 
    int one = 1; 
    non_fundamental_type nft; 

    example<int>().function(one); 
    example<non_fundamental_type>().function(nft); 

    return 0; 
} 

希望它能幫助有類似問題的其他人。