C++std::function和std::bind()的概念

std::function: 一个通用的函数封装器,它允许你存储和调用任何可以被调用的东西,例如函数、函数指针、函数对象、Lambda 表达式等。

std::bind: 用于创建函数对象。一个可调用对象的绑定版本,可以提前绑定某些参数,稍后调用时只需提供剩余的参数。
在某些情况下,你可以将它们结合使用,例如,如果你想创建一个可调用对象,该对象包含绑定的参数,然后将其存储在 std::function 中。这在某些情况下可以提高代码的可读性和灵活性。

示例:

#include 
#include 

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

int main() {
    // 创建一个绑定了参数的可调用对象,绑定参数为2,
    // 占位符_1表示稍后调用时传入的第1个参数放在_1这个位置
    std::function<int(int)> func = std::bind(add, 2, std::placeholders::_1);

    // 调用 std::function
    int result = func(3); // 这里相当于调用 add(2, 3)

    std::cout << "Result: " << result << std::endl;

    return 0;
}

std::functionstd::bind一起使用可以提供一些好处,尤其在以下情况下:

  • 延迟参数绑定:你可以使用std::bind在创建std::function对象时部分绑定参数,然后稍后再提供其余的参数。这使得你可以在调用可调用对象时动态地确定一些参数值。

  • 增强可读性:std::bind允许你清晰地指定参数的绑定方式,这可以提高代码的可读性,特别是当你处理复杂的函数签名时。

  • 灵活性:结合使用std::function和std::bind可以让你更容易地操作和传递可调用对象。这对于实现通用接口或处理回调函数时特别有用。

  • 减少代码冗余:如果你需要多次调用具有相同部分绑定的可调用对象,结合使用std::function和std::bind可以减少重复的绑定代码。


在不需要提前绑定参数的情况下,可以不使用std::bind()。在C++11引入Lambda表达式后,使用更加灵活和方便。以下是一个示例,演示如何使用 std::function 类型变量存储一个普通函数Lambda表达式

Copy code
#include 
#include 

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

int main() {
    // 使用 std::function 存储普通函数
    std::function<int(int, int)> func1 = add;

    // 使用 Lambda 表达式
    std::function<int(int, int)> func2 = [](int a, int b) {
        return a + b;
    };

    int result1 = func1(2, 3); // 调用 add 函数
    int result2 = func2(4, 5); // 调用 Lambda 表达式

    std::cout << "Result 1: " << result1 << std::endl;
    std::cout << "Result 2: " << result2 << std::endl;

    return 0;
}


考虑这种情况:可调用对象是类的成员函数

  • 成员函数是跟具体的对象绑定的,它可以操作该对象中的其他成员变量或者调用其他成员函数。成员函数可以做到分辨哪个对象在调用我是因为有隐藏this指针指向当前调用该函数的对象。
  • 比如obj.funcAdd(1,2),效果实际上是Obj::funcAdd(&obj, 1, 2);
  • 因此如果可调用对象是普通成员函数,我们要绑定一个参数,即指向调用对象的指针。

因此,比较推荐std::function与std::bind()配合使用,或者用lambda表达式

  • 当在一个成员函数中创建函数指针指向另一个普通成员函数时,绑定参数为this

    #include 
    #include 
    
    class MyClass {
    public:
        void func1(int value) {
            std::cout << "func1: " << value << std::endl;
        }
    
        void func2(int value) {
            std::cout << "func2: " << value << std::endl;
        }
    
        void doSome() {
            // 使用 std::bind 创建 std::function 对象,将其绑定到 func2
            std::function<void(MyClass*, int)> functionPtr = 
            	std::bind(&MyClass::func2, this, std::placeholders::_2);
            
            // 调用函数指针,传入对象实例指针和参数
            functionPtr(42);
        }
    };
    
    int main() {
        MyClass obj;
        obj.doSome();
    
        return 0;
    }
    

    当然也可以手动传入this
    比如:std::bind(&MyClass::func2, std::placeholders::_1, std::placeholders::_2);
    调用:functionPtr(this, 42);

  • 利用lambda表达式作为可调用对象(在成员函数内,创建lambda可直接捕获this指针)

    #include 
    #include 
    
    class MyClass {
    public:
        void func1(int value) {
            std::cout << "func1: " << value << std::endl;
        }
    
        void func2(int value) {
            std::cout << "func2: " << value << std::endl;
        }
    
        void doSome() {
            // 使用 Lambda 表达式捕获 this 指针
            std::function<void(int)> functionPtr = [this](int value) {
                MemberFunction2(value);
            };
            
            // 调用函数指针,不需要传递 this 指针
            functionPtr(42);
        }
    };
    
    int main() {
        MyClass obj;
        obj.doSome();
    
        return 0;
    }
    
  • 还有一种简单的情况:如果是在想存储某个对象的某个成员函数的指针,则需要传入该对象的地址

    #include 
    #include 
    
    class MyClass {
    public:
        void func(int value) {
            std::cout << "func: " << value << std::endl;
        }
    };
    
    int main() {
        MyClass obj;
        
        // 创建 std::function 对象,提前绑定&obj,如果不绑定则需要手动传入
        std::function<void(int)> funcPtr = 
        	std::bind(&MyClass::func, &obj, std::placeholders::_1);
        
        funcPtr(42);
        
        return 0;
    }
    

你可能感兴趣的:(C++,c++,算法,开发语言)