模板化函数是应该按值还是通过右值引用获取lambda参数?

Jos*_*vin 29 c++ lambda templates g++ c++11

C++ 11模式下的GCC 4.7让我定义了一个以两种不同方式获取lambda的函数:

// by value
template<class FunctorT>
void foo(FunctorT f) { /* stuff */ }
Run Code Online (Sandbox Code Playgroud)

和:

// by r-value reference
template<class FunctorT>
void foo(FunctorT&& f) { /* stuff */ }
Run Code Online (Sandbox Code Playgroud)

但不是:

// by reference
template<class FunctorT>
void foo(FunctorT& f) { /* stuff */ }
Run Code Online (Sandbox Code Playgroud)

我知道我可以取消模板化函数,只需要使用std :: functions,但是foo它很小并且内联,我想给编译器提供最好的机会来内联调用它.在前两个中,如果我特别知道我正在传递lambdas,那么这对性能来说是优选的,为什么不允许将lambda传递给最后一个?

Xeo*_*Xeo 31

FunctorT&&是一个通用引用,可以匹配任何东西,而不仅仅是rvalues.它是在C++ 11模板中传递内容的首选方式,除非您绝对需要副本,因为它允许您使用完美转发.通过访问值std::forward<FunctorT>(f),f如果之前的话,将再次生成rvalue,否则将其保留为左值.在此处阅读有关转发问题的更多信息,std::forward在此处阅读有关如何std::forward实际工作的分步指南.也是一个有趣的读物.

FunctorT& 只是一个简单的左值引用,你不能绑定临时值(lambda表达式的结果).

  • @JosephGarvin:如果你没有进一步传递,那么`std :: forward`就没有实际意义了:不,不是.想象任何一个算子(不是特别是lambdas),在左值和左值都有一个`运算符()`**ref-qualified*(见[here](http://stackoverflow.com/a/8610728/500104)),而右翼的人做了不同的事情.如果在传入临时时不使用`std :: forward`,则会调用lvalue重载.基本上,你*做*传递函子 - 到它自己的成员函数.;) (2认同)
  • 所以,如果我正确理解,到处都有我需要模板类型参数的模板代码,我应该用&&,每次我使用参数时我都没有明确地想要副本我应该使用std :: forward <T>?这似乎是一吨额外的样板...... (2认同)

Die*_*ühl 5

创建lambda函数时,您将获得一个临时对象.您不能将临时绑定到非const l值引用.实际上,您无法直接创建引用lambda函数的l值.

当您使用函数T&&的参数类型声明函数模板时,T const&如果将const对象传递给函数,T&如果将非const l值对象传递给它,并且T传递它是临时的.也就是说,当传递临时函数声明时,将采用r值引用,该引用可以在不移动对象的情况下传递.当通过值显式传递参数时,概念上复制或移动临时对象,尽管通常省略此复制或移动.如果只将临时对象传递给函数,前两个声明将执行相同的操作,尽管第一个声明可能会引入移动或复制.

  • *"我知道你认为你理解你的想法,但我不确定你是否意识到你所听到的并不是我的意思."* - 艾伦格林斯潘在演讲期间向学生提问. (5认同)