C++仿函数(三)bind和lambda

头文件

#include<functional>

1. bind

示例一

void useBindDemo() {
    set<int> myset;
    myset.insert(3);
    myset.insert(4);
    myset.insert(5);
    vector<int> vec;
    transform(myset.begin(), myset.end(), back_inserter(vec), bind(multiplies<int>(), placeholders::_1, 10));
    copy(vec.begin(), vec.end(), ostream_iterator<int>(cout, " "));
}

示例二

//convert a regular function into functor
double Pow(double x, double y) {
    return pow(x, y);
}
void useBindDemo2() {
    set<int> myset;
    myset.insert(3);
    myset.insert(4);
    myset.insert(5);
    deque<int> d;
    //vector<int> d;
    auto f = function<double (double, double)>(Pow);
    transform(myset.begin(), myset.end(), back_inserter(d), bind(f, placeholders::_1, 2));
        // d {9,16,25}
}

将某个容器中某个区间范围的数属于哪个范围

void useBindDemo3() {
    set<int> myset;
    for (int t = 0; t < 20; t++) {
        myset.insert(t);
    }
    vector<int> d;
    transform(myset.begin(), myset.end(), back_inserter(d),
        bind(logical_and<bool>(),
            bind(greater<int>(), placeholders::_1, 2),
            bind(less<int>(), placeholders::_1, 10)));
            //d {0 0 0 1 1 1 1 1 1 0 ......}
    copy(d.begin(), d.end(), ostream_iterator<int>(cout, " "));
}

2. bind常和this一起使用

通常我们见到bind的时候他通常和std::function或者函数指针差不多。
但是std::function通常说的是某类函数长什么样子,比如输入为两个int返回为bool的可以定义为

using func = std::functiom<bool(int,int)>;

但是如果我我们想用某个具体的函数时,如果使用函数指针可以这样写

bool func_1(int a, int b) { // ... }
void* func_ptr = &func_1;

那么上面的写法实际上可以写成使用bind的

#include <iostream>
#include <functional>

bool func_1(int a, int b) {
  bool ret = (a+b) > 0 ? true : false;
  return ret;
}

auto func_ptr = std::bind(func_1,std::placeholders::_1, std::placeholders::_2);

我们想想其实上面使用bind和函数指针是没有什么区别的。但是如果在面向对象的编程中,我们使用函数指针就会遇到麻烦。
比如一个函数在类里面,那就是成员函数,而成员函数都是属于某个实例的,如何处理这个this问题,处理成函数指针时,##### 我们可以加上static关键字给这个函数。
但是有了bind就不一样了。我们可以将this作为参数传入。其实这个也很简单,如果使用过std::thread的人都会看到样大代码,如果使用类的成员函数创建新线程就会传入一个this指针。
说白了,就是要说明,你这个函数到底是那个this指针的函数。
传入this指针至少也分两种,类内使用和类外使用。

2.1 类内使用
auto fun_ptr = std::bind(&类名::函数名,this, _1, _2);
2.2 类外使用
A a; // class A
auto fun_ptr = std::bind(&类名::函数名, &a, _1, _2);

这里如何理解bind和this呢,其实大家如果知道原型模式,甚至更简单的复制构造函数,明白这个就简单。this就是this。

将某个范围的数拷贝到容器中

bool needCopy(int x) {
        return (x > 2 && x < 10);
}

void useBindDemo4() {
    set<int> myset;
    for (int t = 0; t < 20; t++) {
        myset.insert(t);
    }
    vector<int> d;
    transform(myset.begin(), myset.end(), back_inserter(d),needCopy);
}

这里我们发现,这拷贝进去的是 0 1 啊,不是我们想要的啊。那我们应该修改啊。自己尝试下吧。

3. lambda

void useLambda() {
    set<int> myset;
    for (int t = 0; t < 20; t++) {
        myset.insert(t);
    }
    vector<int> d;
    transform(myset.begin(), myset.end(), back_inserter(d),
        [](int x) {return ((x > 2) && (x < 10)) ? x : 0; });

}

3.1 lambda函数[=] [&]

这个很简单
[=] 是值拷贝,就是如果使用到当前环境中的变量,就是值拷贝。什么叫值拷贝。
这个刚学习c的函数就有

void add(int a) { a++;}
int main() {
 int a = 1;
  add(a);
}

a不会因为调用add函数就改变自身在main中的值。
而[&]就是引用拷贝,顾名思义,就是用的数据本身。
什么时候会用到{}这种函数呢,就是不想创建新的函数或者这个函数比较简单。
举个不想创建的新的函数的例子。
比如你写得某个函数只会用到一次,你就不应该想着把这个单独隔离成一个函数。
在比如说这个函数就只有几行代码,比如重写sort函数时,我想比较两个值的大小让后按照从小到大的顺序排列。

sort(a.begin(), a.end(), [](int b, int c) { return b < c; });

原文链接: https://www.cnblogs.com/cyssmile/p/12803641.html

欢迎关注

微信关注下方公众号,第一时间获取干货硬货;公众号内回复【pdf】免费获取数百本计算机经典书籍;

也有高质量的技术群,里面有嵌入式、搜广推等BAT大佬

    C++仿函数(三)bind和lambda

原创文章受到原创版权保护。转载请注明出处:https://www.ccppcoding.com/archives/345157

非原创文章文中已经注明原地址,如有侵权,联系删除

关注公众号【高性能架构探索】,第一时间获取最新文章

转载文章受原作者版权保护。转载请注明原作者出处!

(0)
上一篇 2023年3月2日 上午3:05
下一篇 2023年3月2日 上午3:05

相关推荐