一、符号修饰与函数签名
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
总结
到此这篇关于c++11 符号修饰与函数签名、函数指针、匿名函数、仿函数、std::function与std::bind的文章就介绍到这了,更多相关c++11 符号修饰符与函数内容请搜索呐喊html" target="_blank">教程以前的文章或继续浏览下面的相关文章希望大家以后多多支持小牛知识库!
> < li> 有什么不同吗? “保存/转移”功能的最佳方式是什么?
多亏了C11,我们收到了系列的仿函数包装器。不幸的是,我一直只听到关于这些新添加的不好的消息。最受欢迎的是它们非常慢。我测试了它,与模板相比,它们真的很糟糕。 111毫秒对1241毫秒。我认为这是因为模板可以很好地内联,而通过虚拟调用覆盖内部。 显然,在我看来,模板也有其问题: 它们必须以头的形式提供,这不是您在以封闭代码形式发布库时可能不希望做的事情, 因此,我可以假设s可以用作传递函子的事实标
主要内容:匿名函数的语法在 C# 中,可以将匿名函数简单的理解为没有名称只有函数主体的函数。匿名函数提供了一种将代码块作为委托参数传递的技术,它是一个“内联”语句或表达式,可在任何需要委托类型的地方使用。匿名函数可以用来初始化命名委托或传递命名委托作为方法参数。 提示:无需在匿名函数中指定返回类型,返回值类型是从方法体内的 return 语句推断出来的。 匿名函数的语法 匿名函数是通过使用 delegate 关键字创建的
在 C 中实现回调函数时,我是否仍应使用 C 样式函数指针: 或者我应该使用std::函数:
往往,我们一提到指针函数和函数指针的时候,就有很多人弄不懂。下面详细为大家介绍C语言中指针函数和函数指针。 指针函数 当一个函数声明其返回值为一个指针时,实际上就是返回一个地址给调用函数,以用于需要指针或地址的表达式中。 格式: 类型说明符 * 函数名(参数) 由于返回的是一个地址,所以类型说明符一般都是int。 在c语言中,函数也是一种类型,可以定义指向函数的指针。我们知道,指针变量的内存单元
5.6. 匿名函数 拥有函数名的函数只能在包级语法块中被声明,通过函数字面量(function literal),我们可绕过这一限制,在任何表达式中表示一个函数值。函数字面量的语法和函数声明相似,区别在于func关键字后没有函数名。函数值字面量是一种表达式,它的值被成为匿名函数(anonymous function)。 函数字面量允许我们在使用函数时,再定义它。通过这种技巧,我们可以改写之前对st