xml*_*lmx 16 c++ lambda function calling-convention c++11
以下代码是使用VC++ 2012编译的:
void f1(void (__stdcall *)())
{}
void f2(void (__cdecl *)())
{}
void __cdecl h1()
{}
void __stdcall h2()
{}
int main()
{
f1(h1); // error C2664
f2(h2); // error C2664
f1([](){}); // OK
f2([](){}); // OK
auto fn = [](){};
f1(fn); // OK
f2(fn); // OK
}
Run Code Online (Sandbox Code Playgroud)
我认为错误是正常的,但OK可以是异常的.
所以,我的问题是:
什么是C++ lambda函数的调用约定?
如何指定C++ lambda函数的调用约定?
如果没有定义调用约定,那么在调用lambda函数后如何正确地回收堆栈空间?
编译器是否自动生成lambda函数的多个版本?即作为以下伪代码:
[] __stdcall(){};
[] __cdecl(){}; 等等
yoh*_*hjp 14
在VC++ 2012上,当您将"无状态lambda转换为函数指针" 时,编译器会选择自动调用无状态lambdas(没有捕获变量)的转换.
Lambda表达式
[...]此外,在Visual Studio 2012中的Visual C++中,无状态lambda可以转换为函数指针.[...](Visual Studio 2012中的Visual C++甚至比这更好,因为我们已经将无状态lambda转换为具有任意调用约定的函数指针.当你使用期望诸如
__stdcall函数指针之类的东西时,这很重要..)
编辑:
注意:调用转换超出了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拉姆达型只提供了一个λ-体实现(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;
Run Code Online (Sandbox Code Playgroud)