模板传递值或const引用或...?

时间:2011-02-02 16:18:10

标签: c++ templates pass-by-reference pass-by-value

我可以这样写一个模板化的函数

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

或者这样

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

我猜第二个选项可以更加优化,因为它明确地避免了副本,但我怀疑它也可能因某些特定类型T(例如仿函数?)而失败。 那么,什么时候应该使用第一个选项,何时使用第二个选项?我previous question的答案中还有boost::call_traits<T>::param_typeboost::reference_wrapper,但人们不会在任何地方使用它们,是吗?这有经验法则吗?感谢。

5 个答案:

答案 0 :(得分:11)

  

这有经验法则吗?

关于何时使用按引用传递和按值传递的相同一般规则适用。

如果您希望T始终是数字类型或复制非常便宜的类型,那么您可以按值获取参数。如果您打算将参数的副本复制到函数中的局部变量中,那么您应该按值将其取值为help the compiler elide copies that don't really need to be made.

否则,请参考参数。对于复制成本低廉的类型,它可能更昂贵,但对于其他类型,它会更快。如果您发现这是一个性能热点,您可以为不同类型的参数重载函数,并为每个参数执行正确的操作。

答案 1 :(得分:6)

  

我怀疑它也可能因某些特定类型而失败

通过引用传递给const是唯一一个“永不”失败的传递机制。它不对T提出任何要求,它接受左值和右值作为参数,并允许隐式转换。

答案 2 :(得分:3)

你不应该唤醒死者,但要解决类似问题,这里有一些示例代码,说明如何使用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;
}

希望它可以帮助处理类似问题的其他人。

答案 3 :(得分:0)

除了James McNellis所写的内容之外,我只想补充一点,您可以将模板专门用于参考类型(for example like this

答案 4 :(得分:0)

boost::traits有一个类型特征,根据T:

选择“最佳”类型

call_traits<T>::param_type

如前所述,没有特定于模板的问题。