C++11新特性之八——函数对象function

http://www.cnblogs.com/yyxt/p/3987717.html

详细请看《C++ Primer plus》(第六版中文版)

http://www.cnblogs.com/lvpengms/archive/2011/02/21/1960078.html

备注:

函数对象
尽管函数指针被广泛用于实现函数回调,但C++还提供了一个重要的实现回调函数的方法,那就是函数对象。函数对象(也称“函数符”)是重载了“()”操作符的普通类对象。因此从语法上讲,函数对象与普通的函数行为类似。
用函数对象代替函数指针有几个优点:

  首先,因为对象可以在内部修改而不用改动外部接口,因此设计更灵活,更富有弹性。函数对象也具备有存储先前调用结果的数据成员。在使用普通函数时需要将先前调用的结果存储在全程或者本地静态变量中,但是全程或者本地静态变量有某些我们不愿意看到的缺陷。

  其次,在函数对象中编译器能实现内联调用,从而更进一步增强了性能。这在函数指针中几乎是不可能实现的。

  C++11还提供了limbda表达式来实现函数的灵活调用。详见《C++ Primer Plus》第18章。

----------------------------------------------------------------------------------------------------------------------------------------------------------

【以下转自】http://www.cnblogs.com/hujian/archive/2012/12/07/2807605.html

function是一组函数对象包装类的模板,实现了一个泛型的回调机制。function与函数指针比较相似,优点在于它允许用户在目标的实现上拥有更大的弹性,即目标既可以是普通函数,也可以是函数对象和类的成员函数,而且可以给函数添加状态。
声明一个function时,需要给出所包装的函数对象的返回值类型和各个参数的类型。比如,声明一个function,它返回一个bool类型并接受一个int类型和一个float类型的参数,可以像下面这样:
function<bool (int, float)> f;

下面简要介绍一下function的比较重要的几个接口。

function();
缺省构造函数,创建一个空的函数对象。如果一个空的function被调用,将会抛出一个类型为bad_function_call的异常。
template <typename F> function(F g);

这个泛型的构造函数接受一个兼容的函数对象,即这样一个函数或函数对象,它的返回类型与被构造的function的返回类型或者一样,或者可以隐式转换,并且它的参数也要与被构造的function的参数类型或者一样,或者可以隐式转换。注意,也可以使用另外一个function实例来进行构造。这样做,并且function g为空,则被构造的function也为空。使用空的函数指针和空的成员函数指针也会产生空的function。如果这样做,并且function g为空,则被构造的function也为空。使用空的函数指针和空的成员函数指针也会产生空的function。

template <typename F> function(reference_wrapper<F> g);
这个构造函数与前一个类似,但它接受的函数对象包装在一个reference_wrapper中,用以避免通过值来传递而产生函数或函数对象的一份拷贝。这同样要求函数对象兼容于function的签名。
function& operator=(const function& g);
赋值操作符保存g中的函数或函数对象的一份拷贝;如果g为空,被赋值的函数也将为空。
template<typename F> function& operator=(F g);
这个泛型赋值操作符接受一个兼容的函数指针或函数对象。注意,也可以用另一个 function 实例(带有不同但兼容的签名)来赋值。这同样意味着,如果g是另一个function实例且为空,则赋值后的函数也为空。赋值一个空的函数指针或空的成员函数指针也会使function为空。
bool empty() const;
这个成员函数返回一个布尔值,表示该function是否含有一个函数或函数对象。如果有一个目标函数或函数对象可被调用,它返回 false 。因为一个function可以在一个布尔上下文中测试,或者与0进行比较,因此这个成员函数可能会在未来版本的库中被取消,你应该避免使用它。
void clear();
这个成员函数清除 function, 即它不再关联到一个函数或函数对象。如果function已经是空的,这个调用没有影响。在调用后,function肯定为空。令一个function为空的首选方法是赋0给它;clear 可能在未来版本的库中被取消。
result_type operator()(Arg1 a1, Arg2 a2, ..., ArgN aN) const;
调用操作符是调用function的方法。你不能调用一个空的 function ,那样会抛出一个bad_function_call的异常。调用操作符的执行会调用function中的函数或函数对象,并返回它的结果。
下面分别给出使用function来包装普通函数,函数对象和类的成员函数的参考代码。
1、普通函数
复制代码
1 int Add(int x, int y)
2 
3 {
4             return x+y;
5 }
6 function<int (int,int)> f = Add;
7 int z = f(2, 3);
复制代码

2、函数对象

复制代码
 1 class CStudent2 {3 public:4             void operator() (string strName, int nAge)5             {6                 cout << strName << " : " << nAge << endl; 7             }8 };9 
10 CStudent stu;
11 function<void (string, int)> f = stu;
12 f("Mike",  12);
复制代码

3、类的成员函数

复制代码
 1 struct TAdd2 {3     int Add(int x,int y)4     {5         return x+y;6     }7 };8 9 function<int  (TAdd *, int, int)> f = TAdd::Add;
10 TAdd tAdd;
11 f(&tAdd, 2, 3);   // 如果前面的模板参数为传值或引用,直接传入tAdd即可
复制代码

接下来我们来看看使用function来保存函数对象状态的情况。考虑下面的代码:

复制代码
 1 class CAdd2 {3 public:4     CAdd():m_nSum(0) { NULL; }5     int operator()(int i)  //重载 () 运算符6     {7           m_nSum += i;8           return m_nSum;9     }
10 
11     int Sum() const 
12     {
13         return m_nSum;
14     }
15 
16 private:
17     int m_nSum;
18 };
19 
20 int main() 
21 {
22     CAdd add;
23     function<int (int)> f1 = add;
24     function<int (int)> f2 = add;
25     cout << f1(10) << "," << f2(10) << "," << add.Sum() << endl;
26     return 0;
27 }
复制代码
可能和大家想象的结果不一样,上面程序的输出是:10,10,0。我们将同一个函数对象赋值给了两个function,然后分别调用了这两个function,但函数对象中m_nSum的状态并没有被保持,问题出在哪儿呢?这是因为function的缺省行为是拷贝一份传递给它的函数对象,于是f1和f2中保存的都是add对象的拷贝,调用f1和f2后,add对象中的值并没有被修改。

C++ 11中提供了ref和cref函数,来提供对象的引用和常引用的包装。要使function能够正确地保存函数对象的状态,我们可以这样来修改代码:

1 CAdd add;
2 function<int(int)> f1 = ref(add);
3 function<int(int)> f2 = ref(add);
另外,在两个function之间赋值时,如果源function保存的是函数对象的拷贝,则目标function保存的也是函数对象的拷贝;如果源function保存的是函数对象的引用,则目标function保存的也是函数对象的引用。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/384215.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

从零开始学C++之STL(八):函数对象、 函数对象与容器、函数对象与算法

http://blog.csdn.net/jnu_simba/article/details/9500219 一、函数对象 1、函数对象&#xff08;function object&#xff09;也称为仿函数&#xff08;functor&#xff09; 2、一个行为类似函数的对象&#xff0c;它可以没有参数&#xff0c;也可以带有若干参数。 3、任何重载…

树状数组初步理解

学习树状数组已经两周了&#xff0c;之前偷懒一直没有写&#xff0c;赶紧补上防止自己忘记&#xff08;虽然好像已经忘得差不多了&#xff09;。 作为一种经常处理区间问题的数据结构&#xff0c;它和线段树、分块一样&#xff0c;核心就是将区间分成许多个小区间然后通过对大区…

Linux socket编程(二) 服务器与客户端的通信

http://www.cnblogs.com/-Lei/archive/2012/09/04/2670964.html上一篇写了对套接字操作的封装&#xff0c;这一节使用已封装好的Socket类实现服务器与客户端的通信&#xff08;Socket的定义见上篇Socket.h) 服务器端&#xff1a; ServerSocket.h #ifndef SERVERSOCKET_H #defin…

UNIX网络编程:I/O复用技术(select、poll、epoll)

http://blog.csdn.net/dandelion_gong/article/details/51673085 Unix下可用的I/O模型一共有五种&#xff1a;阻塞I/O 、非阻塞I/O 、I/O复用 、信号驱动I/O 、异步I/O。此处我们主要介绍第三种I/O符复用。 I/O复用的功能&#xff1a;如果一个或多个I/O条件满足&#xff08;输…

解决iex -S mix报错

执行iex -S mix命令的时候会遇到如下错误&#xff1a; 执行 mix deps.get 然后就可以运行 iex -S mix了 其中&#xff0c;有可能会出现 按照其网站下载相应文件&#xff0c;复制到项目根目录下&#xff0c;然后执行命令&#xff08;mix local.rebar rebar ./rebar&#xff09;即…

Anker—工作学习笔记

http://www.cnblogs.com/Anker/archive/2013/08/17/3263780.html 1、基本知识 epoll是在2.6内核中提出的&#xff0c;是之前的select和poll的增强版本。相对于select和poll来说&#xff0c;epoll更加灵活&#xff0c;没有描述符限制。epoll使用一个文件描述符管理多个描述符&am…

Linux网络编程——tcp并发服务器(I/O复用之select

http://blog.csdn.net/lianghe_work/article/details/46519633 与多线程、多进程相比&#xff0c;I/O复用最大的优势是系统开销小&#xff0c;系统不需要建立新的进程或者线程&#xff0c;也不必维护这些线程和进程。 代码示例&#xff1a; [csharp] view plaincopy #include &…

Linux下的I/O复用与epoll详解

http://www.cnblogs.com/lojunren/p/3856290.html 前言 I/O多路复用有很多种实现。在linux上&#xff0c;2.4内核前主要是select和poll&#xff0c;自Linux 2.6内核正式引入epoll以来&#xff0c;epoll已经成为了目前实现高性能网络服务器的必备技术。尽管他们的使用方法不尽相…

数据结构--顺序栈和链式栈

http://www.cnblogs.com/jingliming/p/4602458.html 栈是一种限定只在表尾进行插入或删除操作,栈也是线性表表头称为栈的底部,表尾称为栈的顶部,表为空称为空栈&#xff0c;栈又称为后进先出的线性表,栈也有两种表示:顺序栈与链式栈顺序栈是利用一组地址连续的存储单元&#xf…

数据结构--双链表的创建和操作

http://www.cnblogs.com/jingliming/p/4602144.html#0-tsina-1-42616-397232819ff9a47a7b7e80a40613cfe1 一、双向链表的定义 双向链表也叫双链表&#xff0c;是链表的一种&#xff0c;它的每个数据结点中都有两个指针&#xff0c;分别指向直接后继和直接前驱。所以&#xff0c…

MYSQL错误代码#1045 Access denied for user 'root'@'localhost'

http://blog.csdn.net/lykezhan/article/details/70880845 遇到MYSQL“错误代码#1045 Access denied for user rootlocalhost (using password:YES)” 需要重置root账号权限密码&#xff0c;这个一般还真不好解决。 不过&#xff0c;这几天调试的时候真的遇到了这种问题&#x…

常量变量以及循环

常量 1.三目运算词 三字母词表达字符???([??)]??<{??>} 2.循环 1).数组元素以及变量在内存中的分配顺序 2)goto语句应用 //电脑关机程序 #include<stdio.h> #include <stdlib.h> #include <string.h> #include <windows.h> int ma…

Linux 环境 C语言 操作MySql 的接口范例

http://www.cnblogs.com/wunaozai/p/3876134.html 接上一小节&#xff0c;本来是计划这一节用来讲数据库的增删改查&#xff0c;但是在实现的过程中&#xff0c;出现了一点小问题&#xff0c;也不是技术的问题&#xff0c;就是在字符界面上比较不好操作。比如要注册一个帐号&a…

数组相关运算

数组的初始化 数组及指针在内存中的存储 一维数组在内存中的存储 有关数组的运算 //一维数组 int a[] {1,2,3,4}; printf("%d\n",sizeof(a));//16这里的a表示的是整个数组,计算出的是整个数组的大小,单位为byte printf("%d\n",sizeof(a 0));/*a没有单独…

gets fgets 区别

http://www.cnblogs.com/aexin/p/3908003.html 1. gets与fgets gets函数原型&#xff1a;char*gets(char*buffer);//读取字符到数组&#xff1a;gets(str);str为数组名。 gets函数功能&#xff1a;从键盘上输入字符&#xff0c;直至接受到换行符或EOF时停止&#xff0c;并将读取…

Shuffle'm Up——简单模拟

【题目描述】 A common pastime for poker players at a poker table is to shuffle stacks of chips. Shuffling chips is performed by starting with two stacks of poker chips, S1 and S2, each stack containing C chips. Each stack may contain chips of several diff…

Fire!——两个BFS

【题目描述】 【题目分析】 看到题目后很清楚是两个BFS&#xff0c;可是我觉得对于火的BFS可以转换成判断&#xff0c;我的做法是将火的位置全部记录下来&#xff0c;然后判断某个位置距离每个火的步数是否小于当前步数&#xff0c;可是错了&#xff0c;还不清楚为什么&#x…

函数调用过程(栈桢)

栈桢 首先来看一段代码 #include<stdio.h> int add(int x, int y) {int z x y;return z; } int main() {int a 10;int b 20;int ret add(a, b);printf("ret %d\n",ret);return 0; } 此处是为了给a,b分别开辟空间,这时栈桢如图所示 两条push命令将a,b变…

整型数据存储

//代码1 #include<stdio.h> int main() {char a -1;signed char b -1;unsigned char c -1;printf("a %d, b %d, c %d", a, b, c);return 0; } 1000 0000 0000 0001 -> -1源码 1111 1111 1111 1110 -> -1反码 1111 1111 1111 1111 -> -1补码 对于…

HDU - 4578Transformation——线段树+区间加法修改+区间乘法修改+区间置数+区间和查询+区间平方和查询+区间立方和查询

【题目描述】 HDU - 4578Transformation Problem Description Yuanfang is puzzled with the question below: There are n integers, a1, a2, …, an. The initial values of them are 0. There are four kinds of operations. Operation 1: Add c to each number between ax …