C++ function + Lambda表达式实现函数内置函数

起因:

在做leetcode上的题目时经常遇到需要辅助函数的情况,但是leetcode的特殊方式(输入不用自己处理,只需要写算法主体)会导致solve函数中的部分变量不能够实现全局,不方便传入函数。在被大佬的代码教育之后发现了这个写法,分享给你的同时也可以给自己留下备忘录


正文

function 用法大致和c语言中的函数指针类似(指向函数的指针)

补充:c的函数指针

基本语法:与下面的function用法基本相同

返回类型 + (* +指针名) (参量类型) = 函数名      //()括号不可省略

int print(int x){
    return  x ;
}
int main()
{
    int x;
    cin >> x;
    int (*f) (int) = print ;
    cout <<f(x) << endl;
    cout <<print(x) <<endl; 
    return 0;
}

返回指向函数的指针

基本语法:

声明指针类型: using 指针类型 = (返回类型+*)(参数)

#include <bits/stdc++.h>
using namespace std;
using f = int (*)(int , int );//这是一个指向 int (int , int) 型的函数指针类型
int add(int a ,int b ){
    return  a+b;
}
int sub(int a,int b ){ 
    return  a-b;
}
int mul(int a,int b ){
    return a*b;
}
int dv(int a , int b){
    return a / b;
}
int main()
{
    int a ,b;
    cin >> a >> b;
    f f1 =  add;
    cout << f1(a,b)<< endl;
    vector<f> v {add,sub,mul,dv};//vector 中储存的是指针
    for (auto &x : v){
        cout << x(a,b)<<endl;//通过指针进行调用
    }
    return 0;
}

基本语法:

function <返回值 (参量类型)> 变量名(要指向的函数)

用法其一:

#include <bits/stdc++.h>
#define ll long long 
#define pii pair<int,int>
using namespace std;
int cnt[26];
void print1(){
    cout << "函数1" <<endl;
    return ;
}
void print2(){
    cout << "函数2" <<endl;
    return ;
}
int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    function <void ()> f(&print1);
    f(); //调用第一个函数
    f = &print2;//指向第二个函数
    f();
    return 0;
}

输出结果:

函数1
函数2

tips:function 类型的变量一旦声明了类型(< > 里面的东西) 就只能指向相同类型函数,不能指向其他类型的

例:

void print1(){

    cout << "函数1" <<endl;

    return ;

}

void print2(int x){

    cout << "函数2" <<endl;

    return ;

}

int main() {

    ios::sync_with_stdio(false);

    cin.tie(nullptr);

    function <void ()> f(&print1);

    f(); //调用第一个函数

    f = &print2;//指向第二个函数

    f();

    return 0;

}

很明显会报错,因为第二个函数中有变量而我们定义的f没有变量这个类型,所以不匹配


lambada 表达式

一般用于定义匿名函数,使得代码更加灵活简洁。lambda表达式与普通函数类似,也有参数列表、返回值类型和函数体,只是它的定义方式更简洁,并且可以在函数内部定义。

基本语法:

返回类型  函数名(变量名)  =  [ ] (变量和变量名) -> 返回类型 {函数内容+返回};

例:

 auto add = [] (int a ,int b) -> int {cout <<"这是加法"<<endl;return  a+b;};

    cout << add(1,2)<<endl;

输出结果:

这是加法
3

补充:[ ]内的东西 是 捕获列表,是Lambda表达式是否能够使用外部变量的基础

主要有

[ ]  Lambda 表达式不能使用外部任何变量(全局变量除外)

[=] 按赋值的方式捕获变量(无法修改外部变量)

[&] 按引用的方式捕获,传递的是地址,可以修改外部

[=, &a] 除了变量a之外,按值的方式捕获所有局部变量,变量a使用引用的方式来捕获。这里可以按引用捕获多个,例如 [=, &a, &b,&c]。这里注意,如果前面加了=,后面加的具体的参数必须以引用的方式来捕获,否则会报错。

[&, a] 除了变量a之外,按引用的方式捕获所有局部变量,变量a使用值的方式来捕获。这里后面的参数也可以多个,例如 [&, a, b, c]。这里注意,如果前面加了&,后面加的具体的参数必须以值的方式来捕获。

[a, &b] 以值的方式捕获a,引用的方式捕获b,也可以捕获多个

[this]  捕获this指针,在成员函数中,[=]和[&]也会捕获this指针。


重点来了:function + Lambada 

function<返回类型(参量类型)> 函数名 =  [捕获列表] (参量) {函数体+返回};

或者

function<返回类型(参量类型)> 函数名 =  [捕获列表] (参量) -> 返回类型 {函数体+返回};

例:

2517. 礼盒的最大甜蜜度 - 力扣(Leetcode)

在为了使用二分查找的过程中简化代码()我使用了这个方式来写check函数

顺带一提,这个题目是二分答案,还挺新颖的(孩子没见过世面)

AC代码

class Solution {
public:
    int maximumTastiness(vector<int>& p, int k) {
        sort(p.begin() , p.end());
        int n = p.size();
        //二分答案
        //所有的结果只能在在0到最后一个数字减去第一个数字之间 
        //所以二分 0 - x 这个区间即可得到答案
        int r = p[n - 1] - p[0] , l = 0;
        function <bool(int , int)> check = [&] (int x , int k) {
            int cnt = 1;//当前数字已经选择了
            for (int i = 0 , j = 1 ; j < n ; j ++){
                if (p[j] - p[i] >= x){
                    cnt ++;
                    i = j;
                }
            }
            //如果
            return cnt >= k;//当选择的答案较小时会导致cnt的数量大于k
        };
        while(l <= r){//目标是要略大于想要的答案所以要等于
            int mid = (l + r) >> 1;
            if(check(mid , k)) l = mid+1;
            else r = mid -1;
        }
        return r;
    }
};

function哪里也也可以使用Lambda表达式

 function <bool(int , int)> check = [&] (int x , int k) ->bool{
            int cnt = 1;//当前数字已经选择了
            for (int i = 0 , j = 1 ; j < n ; j ++){
                if (p[j] - p[i] >= x){
                    cnt ++;
                    i = j;
                }
            }
            //如果
            return cnt >= k;//当选择的答案较小时会导致cnt的数量大于k
        };

其余知识:

  • 内联函数,c++ 中每次调用函数都会放入栈中,频繁调用函数会导致堆栈溢出,而内敛函数在调用时会进行代码展开,将所有调用这个函数的调用点都替换为函数的代码,从而避免了堆栈溢出(类内的函数是默认的inline函数)

使用方法:

在函数前面加上inline 即可

一般会放在头文件中进行声明,因为内联函数是可以重复定义的

示例:

#include <bits/stdc++.h>
using namespace std;
inline int print(int x){
        return  x ;
}
int main()
{
   
    int x ; cin >> x;
    cout << print(x) ;//这里会被展开为return x
    return 0;
}

写在最后

谢谢观看!!!

这是一系列记录自己成长的文章,如果对你有帮助的话我会很开心的

顺带上次qq机器人的东西还没写呢(恼)

更详细的可以参考这两篇文章:

深入浅出C++的function - 知乎 (zhihu.com)

C++ Lambda表达式的完整介绍 - 知乎 (zhihu.com)

今日你WA了吗

给大佬磕头orz

  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值