我可以这样写一个模板化的函数
template<class T> void f(T x) {...}
或者这样
template<class T> void f(T const& x) {...}
我猜第二个选项可以更加优化,因为它明确地避免了副本,但我怀疑它也可能因某些特定类型T
(例如仿函数?)而失败。
那么,什么时候应该使用第一个选项,何时使用第二个选项?我previous question的答案中还有boost::call_traits<T>::param_type
和boost::reference_wrapper
,但人们不会在任何地方使用它们,是吗?这有经验法则吗?感谢。
答案 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)