Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/125.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
将引用转发为函子参数的优点 有很多关于新的C++转发引用的讨论。 然而,有时在特定情况下,我仍然不清楚它们是否提供了任何优势_C++_C++11 - Fatal编程技术网

将引用转发为函子参数的优点 有很多关于新的C++转发引用的讨论。 然而,有时在特定情况下,我仍然不清楚它们是否提供了任何优势

将引用转发为函子参数的优点 有很多关于新的C++转发引用的讨论。 然而,有时在特定情况下,我仍然不清楚它们是否提供了任何优势,c++,c++11,C++,C++11,很明显,通过值传递重态函子(就像随机数生成器)不是一个好主意。所以让我们使用引用。好吧,但是 …使用转发引用有什么好处吗 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; } 模板 T函子(tx,函子&f) { T y; //做一

很明显,通过值传递重态函子(就像随机数生成器)不是一个好主意。所以让我们使用引用。好吧,但是

…使用转发引用有什么好处吗

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;
}
模板
T函子(tx,函子&f)
{
T y;
//做一些涉及f(x)的计算,并将其存储在y中
返回y;
}
而不是常量引用

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;
}
模板
T函子(tx,常数函子&f)
{
T y;
//做一些涉及f(x)的计算,并将其存储在y中
返回y;
}
在不转发函子对象的函数中


问题的主要方面是性能方面的考虑。

转发参考版本能够使用
操作符()将
函子绑定到
s,声明const非const

选择取决于
f
的作用,接受右值是否合理,函数对象是否应该很小,引用语义是否有意义。大多数标准的库算法都是按值获取函数对象,因为它们的状态很少甚至没有,按值获取会更有效

获取转发引用的一个好例子是
std::shuffle

template< class RandomIt, class URNG >
void shuffle( RandomIt first, RandomIt last, URNG&& g );
模板
无效随机播放(先随机播放,后随机播放,URNG&&g);
必须参考URNG,因为1)它不需要可复制,2)您确实不想复制它(这两个原因都是因为复制RNG的成本非常高,而且用户通常希望
shuffle
更改RNG的状态;如果使用同一个RNG对象对
shuffle
进行两次调用会导致相同的“随机”顺序,他们会非常惊讶)。您也不能按常量引用获取它,因为这样您就不能调用
操作符()
在其上-生成随机数会更改RNG的状态


然后,在非常量左值引用,
URNG&
和转发引用,
URNG&&
之间进行选择。因为有时您确实希望接受右值URNG,例如,当您希望随机移动到相同的可复制顺序时,因此您可以在调用点创建一个具有固定种子的生成器在正向引用而非常量引用上编译:

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
}
模板
T函子(tx,函子&f)
{
T y;
y=f(x);
返回y;
}
模板
T函子2(tx,常数函子&f)
{
T y;
y=f(x);
返回y;
}
int main()
{
INTA=1;
自动添加a=[=](intx)可变{return++a;};
func(0,add_a);//编译
func2(0,add_a);//未编译
}

因为
mutable
lambda没有
运算符const(int)


换句话说,调用可变lambda将对其进行变异,但是您无法变异常量引用。因此,您需要使用转发引用。

转发引用唯一令人沮丧的事情是,如果您想访问成员类型,您需要使用typename std::remove_reference::type从它们中删除引用,这会弄乱可读性@plasmacel写一个别名,删除一次,再也不用担心它了:)