何时在 lambda 上使用函子
When to use functors over lambdas
是否有一种情况是创建函子比使用 lambda 更有意义?
我知道我的问题实际上与何时使用lambda而不是函子相反,但是我想不出在实践中哪种情况会更喜欢函子而不是lambda。对此有什么想法吗?
lambda 是一个函子 - 只是用较短的语法定义。
问题是这种语法是有限的。它并不总是允许您以最有效和最灵活的方式解决问题 - 或者根本不允许。直到C++14,operator()
甚至不能成为模板。
此外,一个 lambda 只有一个operator()
.您不能提供多个重载来区分参数的类型:
struct MyComparator
{
bool operator()( int a, int b ) const {return a < b;}
bool operator()( float a, float b ) const {return /*Some maths here*/;}
};
.. 或对象参数的值类别(即调用的闭包对象(。您也不能定义特殊成员函数,包括构造函数和析构函数 - 如果函子负责资源怎么办?
lambda 的另一个问题是它们不能递归。当然,正常功能(包括算子功能(也可以。
还要考虑到 lambda 不方便用作关联容器的比较器或智能指针的删除器:不能直接将闭包类型作为模板参数传递,需要从另一个闭包对象构造容器成员。(闭包类型没有默认构造函数!对于块范围的map
来说,这并不麻烦:
auto l = [val] (int a, int b) {return val*a < b;};
std::map<int, int, decltype(l)> map(l);
现在,如果您的map
是数据成员,会发生什么情况?构造函数初始化列表中的什么模板参数,什么初始值设定项?您必须使用另一个静态数据成员 - 但由于您必须在类定义之外定义它,这可以说是丑陋的。
总而言之:Lambda 对更复杂的场景没有用,因为它们不是为它们而生的。它们提供了一种简短而简洁的方法,用于为相应的简单情况创建简单的函数对象。
我会考虑在 lambda 上使用函子,当我
- 需要多个实例。
- 必须进行高级资源处理。
- 需要将函子称为类型。 例如,将其作为模板参数传递。
- (相关(可以为类型(与实例相反(提供一个有意义且通常有用的名称。
- 发现当拆分为子函数时,逻辑可以写得更干净。 在 lambda 中,我们必须将所有内容写入单个函数。
我可以想到两种情况:
- 当函子
携带内部状态时,因此函子存在一个不平凡的生命周期问题。它在使用之间保持"某些东西">
当您必须到处使用相同的代码时,从维护的角度来看,将其编写并保留为自己的标头中的函子可能是一个好主意
lambda 不能在未计算的上下文中使用。一个特别做作的例子是从沙菲克的回答中窃取的:
在许多情况下,它只是无用,因为每个 lambda 都有一个唯一的类型,给出的假设示例:
template<typename T, typename U> void g(T, U, decltype([](T x, T y) { return x + y; }) func); g(1, 2, [](int x, int y) { return x + y; });
声明和调用中的 lambda 类型为 不同(根据定义(,因此这行不通。
因此,即使是具有相同语法的 lambda 也不能代替另一个。在这种情况下,函子将起作用。
- lambda参数转换为constexpr技巧,然后获取带链接的数组
- 何时在引用或唯一指针上使用移动语义
- 可组合的lambda/std::函数与std::可选
- 何时提供默认参数作为模板参数
- C++Boost Asio Pool线程,带有lambda函数和传递引用变量
- 如何建立使用模板函数的lambda函数的尾部返回类型
- C++-明确何时以及如何调用析构函数
- 如何将lambda作为模板类的成员函数参数
- C++从其他 constexpr 创建 lambda 不能按顺序执行 Constexpr
- 在 lambda 捕获中声明的变量的类型推导
- 我可以将调用类的"this"传递给 lambda 函数吗?
- 为什么lambda在clang上崩溃而不是在gcc上崩溃
- 何时在C 11 lambda的定义中捕获需要捕获的变量
- 当使用 std::move 和 lambda 时,何时会发生移动
- 何时解析 C++11 lambda 表达式中的变量引用
- 通用 lambda 与标准模板函数(使用什么以及何时使用)
- 何时在 lambda 上使用函子
- 何时更喜欢lambda中的显式捕获而不是隐式捕获
- 在 C++11 中,何时应该按值捕获 lambda 表达式的绑定变量?
- lambda捕获何时初始化