在C++中调用lambdas的方式是最常用的
Which way of invoking lambdas in C++ is the most idiomatic?
我注意到lambdas既使用函数指针工作,也使用g++
的专用function
类型工作。
#include <functional>
typedef int(*fptr)(int, int);
int apply_p(fptr f, int a, int b) {
return f(a, b);
}
int apply_f(std::function<int(int, int)> f, int a, int b) {
return f(a, b);
}
void example() {
auto add = [](int a, int b) -> int {
return a + b;
};
apply_p(add, 2, 3); // doesn't give an error like I'd expect it to
apply_f(add, 2, 3);
}
我的问题是:以下哪一个最常用?使用一个比另一个有什么危险和/或好处?
我注意到lambdas都使用函数指针以及专用的
function
类型
如果lambda没有捕获任何内容,那么它可能会衰减为函数指针。
以下哪一个最常用?
两者都没有。如果要存储任意可调用对象,请使用function
。如果你只想创建和使用一个,请保持它的通用性:
template <typename Function>
int apply(Function && f, int a, int b) {
return f(a,b);
}
您可以更进一步,使返回和参数类型通用;我将把它作为练习。
使用一个比另一个有什么危险和/或好处?
函数指针版本只适用于(非成员或静态)函数和非捕获Lambda,不允许传递任何状态;只有函数本身及其参数。function
类型可以包装任何可调用的对象类型,无论是否带有状态,因此更通用。然而,这有一个运行时成本:为了隐藏包装的类型,调用它将涉及虚拟函数调用(或类似的调用);并且它可能需要动态存储器分配来保持大类型。
我会说(C++14)
template <class Functor, class... Args>
decltype(auto) apply_functor(Functor&& f, Args&&... args) {
return std::forward<Functor>(f)(std::forward<Args>(args)...);
}
或C++11:
template <class Functor, class... Args>
auto apply_functor(Functor&& f, Args&&... args) ->decltype(std::forward<Functor>(f)(std::forward<Args>(args)...)) {
return std::forward<Functor>(f)(std::forward<Args>(args)...);
}
如果有疑问,请选择std::function
:
-
语法要简单得多,并且与其他类型一致,例如
typedef std::function<int (int, int)> MyAddFunction;
和
typedef int (*MyAddFunction)( int, int );
-
它更通用(它实际上可以采用lambda、纯C函数或函子)
-
更安全的
apply_p(0, 0, 0); // probably crashes at runtime, dereferences null pointer apply_f(0, 0, 0); // doesn't even compile
相关文章:
- 如何在c++中为模板函数实例创建快捷方式
- 在c代码之间共享数据的最佳方式
- 在C++中将函数压缩为两种方式
- 以螺旋方式打印矩阵的程序.(工作不好)
- 为字符串中每 N 个字符插入空格的函数没有按照我认为的方式工作?
- 创建引用向量的优雅方式
- Constexpr替代了新的放置方式,可以让内存中的对象保持未初始化状态
- 使用QQuickFramebufferObject时同步数据的最佳方式是什么
- 不同/较旧的处理器运行c++代码的方式是否不同
- 从嵌套在std::映射中的std::列表中删除元素的最佳方式
- 如果条件为TRUE(最佳方式?),则在do while循环中后置增量
- 重载方法的方式会在使用临时调用时生成编译器错误
- 在reactor中存储eventHandlers的最佳方式是什么
- 如何以优化的方式同时迭代两个间距不相等的数组
- 以线程安全的方式调用"QQuickPaintedItem::updateImage(const QImage&image)"(no QThread)
- 为什么C++有不同的变量初始化方式?
- 在AVX通道中混洗的最佳方式
- 如何重新定义MPI_FLOAT,MPI_DOUBLE以 typedef 的方式
- 如何以静态代码分析友好的方式使用 #define 防护?
- 在C++中调用lambdas的方式是最常用的