C ++内联Lambda参数

问题描述

考虑以下代码

#include <iostream>
#include <functional>

using namespace std;

inline void readandrun(function<void(int)> callback) {
    int i;
    i = 1;
    callback(i);
}

int main(int argc,char *argv[])
{
#ifdef LAMBDA
    readandrun([](int i){ printf("the read number is: %d\n",i);});
#else
    int i;
    i = 1;
    printf("the read number is: %d\n",i);
#endif
    return 0;
}

使用

进行编译
g++ -DLAMBDA -O2 -std=c++17 -S test.cpp -o test_long.S 

涉及同时跳跃的收益代码

g++ -O2 -std=c++17 -S test.cpp -o test_short.S 

没有。哪种方法有意义,但由于在编译时就知道,可以告诉编译器内联lambda参数吗?我愿意切换编译器,但出于完整性考虑:

$ g++ --version
Configured with: --prefix=/Library/Developer/CommandLinetools/usr --with-gxx-include-dir=/usr/include/c++/4.2.1
Apple LLVM version 10.0.1 (clang-1001.0.46.4)
Target: x86_64-apple-darwin18.7.0
Thread model: posix
InstalledDir: /Library/Developer/CommandLinetools/usr/bin

解决方法

[...]是否可以告诉编译器内联lambda参数,因为它在编译时就知道了?

可能性很小(换句话说,-),这主要是因为您使用了std::function,由于其实现的性质,它使用了类型擦除和通过动态分配来实现这一目标。呼叫时,会进行虚拟呼叫,因此会有跳跃。为了内联代码,您可以切换到:

template <typename Callback>
inline void readandrun(Callback callback) {
    int i;
    i = 1;
    callback(i);
}

这样,就可以推断出lambda的确切类型,并且代码对于内联性非常好。


请记住-lambda的类型永远不会为std::function。它(std::function)只是可调用对象的包装,并删除了实际类型。

,

如果您可以使用函数指针而不是std::function作为参数,则可以使函数constexpr

constexpr void readandrun(void(*callback)(int)) {
    int i = 1; // can't use uninitialized variables in constexpr function
    callback(i);
}

See the assembly online

请注意,只有非捕获的lambda可以转换为函数指针。有关捕获lambda的信息,请参见Fureeish's answer。另外,constexpr函数有一些限制,但是另一方面,如果可能,编译器将在编译时执行它们。