菜鸟笔记
提升您的技术认知

std::bind的讲解-ag真人游戏

一、在讲解std::bind之前,我们先来复习下std::function。

std::function 是一个“可调用对象”包装器,是一个类模板,可以容纳除了类成员函数指针之外的所有可调用对象,它可以用统一的方式处理函数、函数对象、函数指针,并允许保存和延迟它们的执行。

什么是可调用对象?

(1)函数指针
(2)具有operator()成员函数的类对象(传说中的仿函数),lambda表达式
(3)可被转换为函数指针的类对象
(4)类成员(函数)指针
(5)bind表达式或其它函数对象

比如:

// 普通函数
int add(int a, int b){return a b;} 
// lambda表达式
auto mod = [](int a, int b){ return a % b;}
// 函数对象类
struct divide{
    int operator()(int denominator, int divisor){
        return denominator/divisor;
    }
};

用std::function将上述类型保存起来:

std::function  a = add; 
std::function  b = mod ; 
std::function  c = divide(); 

二、std::bind

可将std::bind函数看作一个通用的函数适配器,它接受一个“可调用对象”,生成一个新的可调用对象来“适应”原对象的参数列表。

std::bind主要有以下两个作用:
(1)将可调用对象和其参数绑定成一个防函数;
(2)只绑定部分参数,减少可调用对象传入的参数。

1、绑定普通函数

double divide (double x, double y) {
    return x/y;
}
auto divide_half = std::bind (my_divide,_1,2);  
std::cout << fn_half(10) << std::endl; // 输出5

(1)bind的第一个参数是函数名,普通函数做实参时,会隐式转换成函数指针。因此std::bind (divide,_1,2)等价于std::bind (÷,_1,2);
(2)_1表示占位符,位于中,std::placeholders::_1;

2、绑定成员函数

#include 
#include 
using namespace std;
struct foo {
    void sum(int n1, int n2)
    {
        std::cout << n1 n2 << std::endl;
    }
	static int staticmember(int a) { 
        return 66   a; 
    }
    int data = 10;
};
int main() {
    foo foo;
    auto f = std::bind(&foo::sum, &foo, 95, std::placeholders::_1);
    f(5); // 输出100
}

(1)bind绑定类成员函数时,第一个参数表示对象的成员函数的指针,第二个参数表示对象的地址。
(2)必须显示的指定&foo::sum,因为编译器不会将对象的成员函数隐式转换成函数指针,所以必须在foo::sum前添加&;
(3)使用对象成员函数的指针时,必须要知道该指针属于哪个对象,因此第二个参数为对象的地址 &foo;

3、绑定静态成员函数

	auto fun2 = &foo::staticmember;
    cout<

4、绑定成员变量

#include 
#include 
using namespace std;
class testclass4 {
public:
    testclass4() : m_a(100)
    {}
	
public:
    int m_a;
};
int main() {
    testclass4 test4;
    auto fun4 = std::bind(&testclass4::m_a, std::placeholders::_1);
	int var = fun4(test4);
    std::cout<

5、绑定仿函数

#include 
#include 
using namespace std;
class testclass5 {
public:
    testclass5() = default;
	
    testclass5(const testclass5& obj) {
        std::cout<<"testclass5 copy construct."<

6、绑定成员函数时,哪些做法会先调用“拷贝构造函数” ?

#include 
#include 
using namespace std;
class testclass {
public:
    testclass(int a):m_a(a){}
    testclass(const testclass& obj) {
        m_a = obj.m_a   100;
        std::cout<<"copy construct."<

执行结果:

7、传引用参数的问题

当需要把对象传到bind中的参数中时,需要使用ref或者cref。

#include
#include
 
using namespace std;
using namespace placeholders;
 
void alter(int &a, int b) {
    a = b;
}
int main() {
    int a = 5;
    auto f1 = bind(alter, a, _1);      //此处bind中的参数a只是a的一个拷贝,而不是a的引用
    f1(9);                           
    cout << a << endl;                //所以此处a仍为5
 
    auto f2 = bind(alter, ref(a), _1);  //使用ref可以将a的引用传递给bind
    f2(9);
    cout << a << endl;                //所以此处a变成了9
 
    return 0;
}
 
 

8、指向成员函数的指针

#include 
struct foo {
    int value;
    void f1() { std::cout << "f1(" << this->value << ")\n"; }
    void f2() { std::cout << "f2(" << this->value << ")\n"; }
};
void apply(foo* foo1, foo* foo2, void (foo::*fun)()) {
    (foo1->*fun)();  // call fun on the object foo1
    (foo2->*fun)();  // call fun on the object foo2
}
int main() {
    foo foo1{1};
    foo foo2{2};
    apply(&foo1, &foo2, &foo::f1);
    apply(&foo1, &foo2, &foo::f2);
}

(1)成员函数指针的定义:void (foo::*fun)(),调用时传递的实参: &foo::f;

(2)fun为类成员函数指针,所以调用时要通过解引用的方式获取成员函数*fun,即(foo1->*fun)()。

网站地图