转发引用作为函子参数的优点
Advantages of forwarding references as functor arguments
有很多关于新的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;
}
在函数中接受函数对象而不转发它们?
问题的主要方面是对性能的考虑。
选择取决于f
做什么,接受右值是否有意义,是否期望函数对象很小,以及引用语义是否有意义。大多数标准库算法都是按值获取函数对象,因为期望它们很少或没有状态,而按值获取可能更有效。
获取转发引用的一个很好的例子是std::shuffle
:
template< class RandomIt, class URNG >
void shuffle( RandomIt first, RandomIt last, URNG&& g );
URNG必须被参考,因为1)它不需要被复制,2)你真的不想复制它(因为RNG复制起来非常昂贵,因为用户通常希望shuffle
改变RNG的状态;如果对同一个RNG对象的shuffle
的两次调用导致相同的"随机"顺序,他们会非常惊讶)。你也不能通过const引用来获取它,因为那样你就不能对它调用operator()
——生成一个随机数会改变RNG的状态。
则在非const左值引用URNG&
和转发引用URNG&&
之间进行选择。由于有时您确实希望接受右值URNG—例如,当您希望洗牌到相同的可重复顺序时,因此您在调用点创建了一个具有固定种子的生成器—因此选择了后者。
转发引用版本可以绑定Functor
s, operator()
声明为const或非const。
下面是一个编译前向引用而不是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引用。所以你需要使用前向引用
- 将const引用参数初始化为默认参数会导致悬空引用吗
- 通过常量引用传递参数的矩阵模板类
- 非类型指针和引用模板参数,以及在编译时如何/为什么解析它们.c++
- 何时应通过引用传递矢量参数而不是按值传递矢量参数?
- 具有常量引用参数的函数模板专用化
- 作为参数引用
- 在 cpp 文件中隐藏采用模板参数引用的方法
- 如何传递带有通过引用传递的结构参数的函数?
- 将输入参数作为右值引用传递?
- 使用引用与指针将数组作为参数传递
- 根据模板参数引用不同基类的函数
- 默认情况下C++数组作为参数引用
- 对指针C++的参数引用
- 作为非类型模板参数引用
- 重用返回语句或按参数引用返回
- 将参数引用传递给函数C++
- 从另一个参数引用的模板可变参数
- 成员变量多态性和参数引用
- 按参数引用或按参数引用之间的差异
- 无法实例化抽象类:为什么模板参数(引用)导致这种情况