zoukankan      html  css  js  c++  java
  • c++11 符号修饰与函数签名、函数指针、匿名函数、仿函数、std::function与std::bind

    一、符号修饰与函数签名

    1、符号修饰

    编译器将c++源代码编译成目标文件时,用函数签名的信息对函数名进行改编,形成修饰名。GCC的C++符号修饰方法如下:

    1)所有符号都以_z开头

    2)名字空间的名字

      名字空间(或类)的名字前加上N

      名字前还有一个数字,是名字的字符数。比如1C,1是C的长度。

    3)函数名

      与名字空间一样,函数名前也有数字,比如4func,4是func的字符数。

    4)参数

      参数以E开头

    例子

    N::C::func(int) 的函数签名经过修饰为_ZN1N1C4funcEi

    2、函数签名

    函数签名组成部分:包括函数名,参数类型,参数个数和顺序,以及它所在类和命名空间。

    以上任何一个部分的不同,都会导致符号修饰后的名词不同,即导致函数签名不同,故可以区分不同的函数,在调用的时候就不会出错。

    二、函数指针

    例子: int(*p)(int,int)

    语句定义了一个指向函数的指针变量P,这个函数指针可以指向这么一个函数,即返回值为int类型,且有两个int参数的函数,指针p的类型为int(*)(int,int)。

    函数指针的统一定义方式为:

    函数返回类型(* 指针变量名)(函数参数列表)

    简单用法:

    int func(int x);     //定义一个函数

    int (*p)(int x);    //定义一个函数指针

    p=func;      //将函数func的首地址赋值给指针变量p

    三、c++11中的匿名函数(lambda函数,lambda表达式)

    C++11提供了对匿名函数的支持,称为lambda函数(也成为lambda表达式),形式如下

    [capture](parameters)->return-type{body}

    解析:

    capture

      1)、[]        //未定义变量,试图在lambda函数内使用任何外部变量都是错误的

      2)、[x,&y]      //x按值捕获,y按引用捕获

      3)、[&]       //用到的任何外部变量都隐式按引用捕获

      4)、[=]       //用到的任何外部变量都隐式按值捕获

      5)、[&,x]      //x显式按值捕获,其他变量按照引用捕获

      6)、[=,&z]     //z按引用捕获,其他变量按值捕获

    parameters:存储函数的参数,当parameters为空的时候,()可以省去

    return-type:函数的返回值,如果funtion body中存在return语句,则该lambda表达式的返回类型由return语句的返回类型确定。

    body:函数体

    例子:

    auto fun=[](int x){ return x; }

    cout<<fun(1)<<endl;      //输出1

    四、仿函数

    本质:仿函数的本质就是类重载了一个operator(),创建一个行为类似函数的对象。

    例子:

    template<class T>

    stuct plus:public binary_function<T,T,T>{

      T operator()(const  T &x,const T &y) const{return x-y;}

    };

    cout<<"plus="<<plus<int>(2,1)<<endl;        //输出1

    五、std::function与std::bind本质

    1、std::finction

      std::function是函数模板类(是一个类);std::bind是函数模板(是一个函数),其包含在#include<functional>文件中。

    std::function 即把函数对象化,将函数当作一个类的对象,主要目的是期望看到更多的泛型算法,不希望看到使用函数取操作数据的代码

    通过std::function对C++中各种可调用实体(普通函数、lambda表达式,函数指针、以及其他的函数对象等)的封装,形成一个新的可调用的std::function对象,让我们不再纠结那么的的可调用实体。

    例子:

    1)、std::function<int(int a)> func      //声明一个std::function对象

    2)、int test(int){return a};            //普通函数

    3)、auto test=[](int a)->int{return a}   //匿名函数

    4)、class test{              //仿函数

    public:

      int operator()(int a){

        return a;

      }

    };

    5)、class test{            //类成员函数&类静态函数

       public:

          int tseta(int a){return a}

          static int testb(int a){return a;}

    };

    //调用

    //1、普通函数

    func=test;

    func(1);

    //2、匿名函数

    func=test

    func(1);

    //3、仿函数

    test t;

    func=t;

    func(1);

    //4、类成员函数

    test t;

    func=std::bind(&test::testa, t ,std::placeholder::_1);     //std::placeholder::_1 :占位符号

    func(1);

    //5、类静态成员函数

    func=test::testb;

    func(1);

    2、std::bind

    std::bind可以看作一个通用的函数适配器,它接受一个可调用对象,生成一个新的可调用对象来适应原对象的参数列表。

    作用:

    1)std::bind将可调用对象和其参数绑定成一个仿函数

    2)只绑定部分参数,减少可调用对象传入的参数

    例子:

    //1、绑定普通函数

    int test_a(int x,inty){return x+y;}

    auto test_A=std::bind(test_a,_1,10);        //_1:占位符

    test_A(2);                    //12

    //2、绑定类成员函数

    struct test_struct{

      int test_b(int x,int y){

        return x+y;

      }

    };

    test_struct test_tt;

    auto test_B=std::bind(&test_struct::test_b,&test_tt,20,30);       //第一个参数为类成员函数的指针(必须显示指定函数,编译器不帮忙),第二个参数为类对象的地址(指明哪个对象的指针),后面两个为函数test_b的两个参数

    test_B();              //50

  • 相关阅读:
    Task 和 Function
    FPGA中双向端口的设计原理及仿真
    EDK实用实例之LED
    分频电路设计(笔记)
    你了解Promise么
    配置vue多页
    Chrome控制台console的那些属性
    关于读书
    django常用命令
    django 简易博客开发 2 模板和数据查询
  • 原文地址:https://www.cnblogs.com/socks/p/12870700.html
Copyright © 2011-2022 走看看