【C++11】function


注意:使用function需要functional头文件。

function引入

function的作用是将具有相同调用形式的不同类型可调用对象进行类型统一。

相同的调用形式可以简单理解为:参数列表和返回值相同。

C++常见可调用对象有:函数、指针、匿名函数(lambda表达式)、函数对象(重载了函数调用运算符的类)以及使用bind创建的对象。

例如以下几个可调用对象具有相同的调用形式:

// 函数
int add(int a, int b) {
    return a + b;
}

// lambda表达式
auto sub = [](int a, int b) -> int {
  return a - b;
};

// 函数对象
class prod{
public:
    int operator() (int a, int b) {
        return a * b;
    }
};

这些可调用对象的调用形式相同,甚至拥有相同的功能,但是却由于类型千差万别无法统一处理。例如,我们想要统一调用以上可调用对象,使用‘+’来调用add函数,而使用‘-’调用sub匿名函数…
使用分支语句(if else if else)当然是可以做到的,但更推荐以下方式:

/*  使用map映射字符到可调用对象。
	但需要注意,映射的前提是function对不同类型的可调用对象
进行了类型统一。 */
map<char, function<int(int, int)>> cacul{
    {'+', add},
    {'-', sub},
    {'*', prod()}
};

cout << cacul['*'](5, 4) << endl;

function基本操作

function基本操作

// T为调用形式resultType(args)
// 默认初始化
function<T> f;

// 显示构造一个空function
function<T> f(nullptr);

// 在f中存储可调用对象的副本
function<T> f(obj);

单独一个function对象可以用来判断是否此其是否保存有可调用对象。已绑定可调用对象则返回true,否则返回false;

function<T> f;
if(f) {
	...
} else {
	...
}

function对象加上参数列表即可调用其保存的可调用对象。

function<T> f = add;

cout << f(1, 2) << endl; // 返回结果3

function与函数重载

需要注意的是,当函数发生重载时不能直接使用函数名来让function保留可调用对象。例如:

int add(int, int);
// person为自定义类型
person add(person a, person b);

// 二义性错误, 即使参数列表不同
function<int(int, int)> f = add;

可以使用存储函数指针来解决问题,因为指针会进行一次匹配:

// 将add(int, int)版本暂存
int(*p)(int, int) = add;

function<int(int, int)> f = p;

也可以使用匿名函数辅助,因为匿名函数中进行了一次正常的函数调用:

function<int(int, int)> f = [](int a, int b) -> int {
	return add(a, b);
};

“匿名函数递归”

写递归函数时经常会遇到一个问题,递归函数参数中真正随着调用而发生变化的参数很少,一些不变的参数比如:存放数据的数组、常量之类的。虽然在递归过程中不发生变化,但为了获取其数据内容也要出现在递归参数列表,导致递归函数参数列表过于冗长。

要解决这个“麻烦事”,除了将不发生变化的数组之类参数的放到全局,也可以将递归函数放到局部。

以一个简单的逆序打印数组值为例:

// 只有第二个参数必须存在
void dfs(vector<int> v, int i) {
    if(i == v.size()) return;
    dfs(v, i + 1);
    cout << v[i] << endl;
}

将不随调用而变化的参数放到全局

例如将vector放到全局:

vector<int> v;
// 参数列表确实变简洁了,但要维护全局变量
void dfs(int i) {
    if(i == v.size()) return;
    dfs(v, i + 1);
    cout << v[i] << endl;
}

将递归函数放到局部

注意匿名函数是不能直接调用自己的,因为使用 auto 类型说明符声明的变量不能出现在其自身的初始值设定项中。由于function可以保存可调用对象,可以避免出现上述报错(对于偶尔写写算法题的人来说,真可以说是不错的技巧):

function<void(int)> dfs = [&](int i) {
    if(i == v.size()) return;
    dfs(i + 1);
    cout << v[i] << endl;
};
dfs(0);
  • 5
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Sophon、

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值