有很多关于新C ++转发引用的讨论。 然而,有时在特定情况下,我仍然不清楚它们是否提供任何优势。
很明显,按值传递大型状态仿函数(就像随机数生成器一样)并不是一个好主意。所以让我们使用引用。好的,但是......
...使用转发参考(如
)是否有任何优势template <class T, class Functor>
T func(T x, Functor &&f)
{
T y;
// do some computations involving f(x) and store it in y
return y;
}
而不是 const引用
template <class T, class Functor>
T func(T x, const Functor &f)
{
T y;
// do some computations involving f(x) and store it in y
return y;
}
在接受仿函数对象而不转发它们的函数中?
问题的主要方面是绩效考虑。
答案 0 :(得分:7)
选择取决于f
的作用,接受rvalue是否有意义,函数对象是否应该小,以及引用语义是否有意义。大多数标准库算法都按值获取函数对象,因为它们预计几乎没有状态,并且按值获取可以更有效。
转发引用的一个好例子是std::shuffle
:
template< class RandomIt, class URNG >
void shuffle( RandomIt first, RandomIt last, URNG&& g );
URNG必须参考,因为1)它不需要是可复制的,2)你真的不想复制它(两者都是因为RNG复制起来相当昂贵因为用户通常希望shuffle
更改RNG的状态;如果两个具有相同RNG对象的shuffle
的调用导致相同的&#34;随机&#34;那么他们会非常惊讶。订购)。您也无法通过const引用来获取它,因为您无法在其上调用operator()
- 生成随机数会更改RNG的状态。
然后选择非常量左值参考URNG&
和转发参考URNG&&
。因为有时你确实想要接受一个右值URNG - 例如当你想要改组到同一个可重复的顺序时,所以你在调用点创建一个带有固定种子的生成器 - the latter was chosen。
答案 1 :(得分:3)
转发参考版本能够绑定到Functor
,operator()
声明 const 或非const
答案 2 :(得分:1)
这是一个编译前向引用而不是const引用的示例:
template <class T, class Functor>
T func(T x, Functor &&f)
{
T y;
y = f(x);
return y;
}
template <class T, class Functor>
T func2(T x, const Functor &f)
{
T y;
y = f(x);
return y;
}
int main()
{
int a = 1;
auto add_a = [=](int x) mutable { return ++a; };
func(0, add_a); // compile
func2(0, add_a); // does not compile
}
http://coliru.stacked-crooked.com/a/3eeb21a57d66452b
因为mutable
lambda没有operator const (int)
换句话说,调用一个可变的lambda会使它变异,但你不能改变const引用。所以你需要使用前向参考。