lambda函数的默认调用约定

lambda函数的默认调用约定

本文介绍了什么是C ++ lambda函数的默认调用约定?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

下面的代码是用VC ++ 2012编译的:

  void f1(void(__stdcall *)())
{}
$ b $ void f2(void(__cdecl *)())
{}

void __cdecl h1()
{}

void __stdcall h2()
{}

int main()
{
f1(h1); //错误C2664
f2(h2); // error C2664

f1([](){}); // OK
f2([](){}); // OK

auto fn = [](){};

f1(fn); // OK
f2(fn); // OK

我认为错误是正常的,但是OK是不正常的。 / p>

所以,我的问题是:


  1. 如何指定C ++ lambda函数的调用约定?


  2. 如果调用约定没有定义,如何在调用lambda函数之后正确回收堆栈空间?

  3. 编译器是否自动生成多个版本的lambda函数?即如下面的伪代码:

    [] __stdcall(){};

    [] __cdecl( ){};在VC ++ 2012上,编译器选择自动调用无状态的转换。

  4. lambda表达式(没有捕获变量)当你将无状态lambda转换为函数指针。








    c $ c> __ stdcall 函数指针。 编辑:



    注意:调用转换不在C ++ Standard中,它取决于其他规范,如平台ABI(应用程序二进制接口)。



    以下答案基于输出汇编代码,其中。
    所以这只是一个猜测,请向微软询问更多细节; P


    首先,C ++ lambda(-expression)不是函数(也不是函数指针),你可以像调用普通函数一样调用 operator()给lambda对象。
    并且输出汇编代码表示VC ++ 2012通过 __ thiscall 调用转换生成lambda-body


    AFAIK,没有办法。 (可能只有 __ thiscall )

    可能是
    VC ++ 2012 lambda类型提供只有一个lambda-body实现( void operator()()),但为每个调用转换提供了多个用户定义的转换为函数指针 void(__fastcall *)(void), void(__stdcall *)(void)和 void(__cdecl *)(void) type)。

    这是一个例子;

      //输入源代码
    auto lm = [](){/ * lambda-body * /};

    //从VC ++ 2012反转C ++代码输出汇编代码
    class lambda_UNIQUE_HASH {
    void __thiscall operator()(){
    / * lambda-body * /
    }
    //用户定义的转换
    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;


    The following code was compiled with 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
    }
    

    I think the errors are normal yet the OKs are abnormal.

    So, my questions are:

    1. What's the calling convention of a C++ lambda function?

    2. How to specify the calling convention of a C++ lambda function?

    3. If the calling convention is not defined, how to correctly recycle the stack space after having called a lambda function?

    4. Does the compiler automatically generate multiple versions of a lambda function? i.e. as the following pseudo-code:

      [] __stdcall (){};

      [] __cdecl (){}; etc.

    解决方案

    On VC++ 2012, compiler choose automatically calling conversion for stateless lambdas (that has no capture variables) when you convert "stateless lambda to function pointer".

    MSDN C++11 Features:


    EDITED:

    NB: The calling conversion is out of C++ Standard, it depends on other specification such as platform ABI(application binary interface).

    The following answers are based on output assembly code with /FAs compiler option.So it's a mere guess, and please ask Microsoft for more detail ;P

    First of all, C++ lambda(-expression) is NOT a function (nor function pointer), you can call operator() to lambda object like a calling normal function.And output assembly code says that VC++ 2012 generates lambda-body with __thiscall calling conversion.

    AFAIK, there is no way. (It may be only __thiscall)

    Probably No.The VC++ 2012 lambda-type provides only one lambda-body implementation (void operator()()), but provides multiple "user-defined conversion to function pointer" for each calling conversion (operator return function pointer with void (__fastcall*)(void), void (__stdcall*)(void), and void (__cdecl*)(void) type).

    Here is an example;

    // 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;
    

    这篇关于什么是C ++ lambda函数的默认调用约定?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

09-05 09:40