2011-02-02 48 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; 
} 

希望它能帮助有类似问题的其他人。