在 VC++ 2012 上,当您将“无状态 lambda 转换为函数指针”时,编译器会选择自动调用无状态 lambda(没有捕获变量)的转换。
MSDN C++11 特点:
拉姆达斯
[...] 此外,在 Visual Studio 2012 的 Visual C++ 中,无状态 lambda 可转换为函数指针。[...](Visual Studio 2012 中的 Visual C++ 甚至比这更好,因为我们已将无状态 lambda 转换为具有任意调用约定的函数指针。当您使用期望__stdcall
函数指针之类的 API 时,这一点很重要.)
编辑:
注意:调用转换超出了 C++ 标准,它依赖于其他规范,例如平台 ABI(应用程序二进制接口)。
以下答案基于带有/FAs 编译器选项的输出汇编代码。所以这只是一个猜测,请向微软询问更多细节;P
Q1。C++ lambda 函数的调用约定是什么?
Q3。如果未定义调用约定,如何在调用 lambda 函数后正确回收堆栈空间?
首先,C++ lambda(-expression)不是函数(也不是函数指针),您可以operator()
像调用普通函数一样调用 lambda 对象。并且输出汇编代码说 VC++ 2012 生成带有__thiscall
调用转换的 lambda-body。
Q2。如何指定 C++ lambda 函数的调用约定?
AFAIK,没有办法。(可能只有__thiscall
)
Q4。编译器会自动生成多个版本的 lambda 函数吗?即作为以下伪代码:[...]
可能不会。VC++ 2012 lambda-type 仅提供一个 lambda-body 实现 ( void operator()()
),但为每次调用转换提供多个“用户定义的函数指针转换”(操作符返回函数指针,带void (__fastcall*)(void)
,void (__stdcall*)(void)
和void (__cdecl*)(void)
类型)。
这是一个例子;
// input source code
auto lm = [](){ /*lambda-body*/ };
// reversed C++ code from VC++2012 output assembly code
class lambda_UNIQUE_HASH {
void __thiscall operator()() {
/* lambda-body */
}
// user-defined conversions
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;