C ++ 11模式下的GCC 4.7让我定义一个以两种不同方式处理lambda的函数:
// by value
template<class FunctorT>
void foo(FunctorT f) { /* stuff */ }
和
// by r-value reference
template<class FunctorT>
void foo(FunctorT&& f) { /* stuff */ }
但不是:
// by reference
template<class FunctorT>
void foo(FunctorT& f) { /* stuff */ }
我知道我可以取消模板函数,只需要使用std :: functions,但是foo
很小而且内联,我想给编译器提供内联调用f的最佳机会。它在里面。在前两个中,如果我特别知道我正在传递lambdas,那么这对于性能更可取,为什么不允许将lambda传递给最后一个?
答案 0 :(得分:30)
FunctorT&&
是通用引用,可以匹配任何内容,而不仅仅是rvalues。它是在C ++ 11模板中传递内容的首选方式,除非您绝对需要副本,因为它允许您使用完美转发。通过std::forward<FunctorT>(f)
访问该值,如果之前是f
,则会使std::forward
再次成为左值,否则会将其保留为左值。阅读有关转发问题的更多here和std::forward
,并阅读here,了解FunctorT&
如何真正有效的分步指南。 This也是一本有趣的读物。
{{1}}只是一个简单的左值引用,你不能将临时值(lambda表达式的结果)绑定到该值。
答案 1 :(得分:3)
这是一个很好的问题 - 第一部分:按值传递或使用转发。我认为第二部分(以FunctorT&
为参数)得到了合理的回答。
我的建议是:只有在事先知道函数对象时才使用转发来修改其闭包(或捕获列表)中的值。最好的例子:std :: shuffle。它需要一个统一随机数生成器(一个函数对象),每次调用生成器都会修改它的状态。函数对象被转发到算法中。
在所有其他情况下,您应该更愿意传递价值。这不会阻止您通过引用捕获本地并在lambda函数中修改它们。这将像你认为的那样工作。 Dietmar说,复制应该没有开销。内联也将适用,并且可以优化参考。