转发引用作为仿函数参数的优点

时间:2015-09-15 22:04:04

标签: c++ c++11

有很多关于新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;
}

在接受仿函数对象而不转发它们的函数中?

问题的主要方面是绩效考虑。

3 个答案:

答案 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)

转发参考版本能够绑定到Functoroperator()声明 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引用。所以你需要使用前向参考。

相关问题