在VC++ 2012中,编译器会自动选择调用转换来处理无状态捕获变量的lambda表达式,当你将“无状态lambda表达式转换为函数指针”时。
MSDN C++11 Features:
Lambdas
[...] 此外,在Visual Studio 2012中的Visual C++中,无状态lambda表达式可以转换为函数指针。[...] (Visual Studio 2012中的Visual C++甚至更好,因为我们使无状态lambda表达式可以转换为具有任意调用约定的函数指针。这在使用期望像__stdcall
函数指针的API时非常重要。)
编辑:
NB:调用转换不符合C++标准,它取决于其他规范,例如平台ABI(应用程序二进制接口)。
以下答案基于使用/FAs编译器选项的输出汇编代码。因此这只是一个猜测,请向Microsoft询问更多细节;P
Q1. C++ Lambda函数的调用约定是什么?
Q3. 如果未定义调用约定,则如何在调用Lambda函数后正确回收堆栈空间?
首先,C++ lambda(表达式)不是函数(也不是函数指针),您可以像调用普通函数一样调用operator()
到lambda对象。
并且输出汇编代码显示VC++ 2012使用__thiscall
调用转换生成lambda体。
Q2. 如何指定C++ Lambda函数的调用约定?
据我所知,没有办法。(可能只有__thiscall
)
问题4:编译器是否会自动生成多个lambda函数版本?即如下伪代码:
[...]
可能不会。VC++ 2012的lambda类型只提供一个lambda-body实现(void operator()()
),但为每个调用转换提供多个“用户定义的函数指针转换”(操作符返回函数指针,具有void (__fastcall*)(void)
、void (__stdcall*)(void)
和void (__cdecl*)(void)
类型)。
以下是一个示例:
auto lm = [](){ };
class lambda_UNIQUE_HASH {
void __thiscall operator()() {
}
typedef void (__fastcall * fp_fastcall_t)();
typedef void (__stdcall * fp_stdcall_t)();
typedef void (__cdecl * fp_cdecl_t)();
operator fp_fastcall_t() { ... }
operator fp_stdcall_t() { ... }
operator fp_cdecl_t() { ... }
};
lambda_UNIQUE_HASH lm;