Skip to content

Latest commit

 

History

History
232 lines (155 loc) · 7.84 KB

C++016:深入理解C++中的stdbind:从基础到进阶.md

File metadata and controls

232 lines (155 loc) · 7.84 KB
title: '深入理解C++中的`std::bind`'
categories:
  - [开发,cpp]
tags:
  - c++
  - cpp

深入理解C++中的std::bind:从基础到进阶

在C++编程中,函数对象(Functor)和回调机制是非常重要的概念。std::bind是C++标准库中一个非常强大的工具,它允许我们将函数、成员函数、甚至是函数对象绑定到特定的参数上,生成一个新的可调用对象。这个新的可调用对象可以在稍后被调用,且调用时可以省略部分参数,或者重新排列参数的顺序。

本文将带你从基础到进阶,逐步深入理解std::bind的用法和原理。我们将通过代码示例和详细的解释,帮助你掌握这个强大的工具。


1. 什么是std::bind

std::bind是C++11引入的一个函数模板,位于<functional>头文件中。它的主要作用是将一个可调用对象(如函数、函数指针、成员函数指针、函数对象等)与一些参数绑定在一起,生成一个新的可调用对象。

简单来说,std::bind可以让你“预先”设置函数的部分参数,生成一个新的函数对象,这个函数对象可以在稍后被调用时,只需要提供剩余的参数。


2. 基础用法:绑定普通函数

我们先从一个简单的例子开始,了解std::bind的基本用法。

示例1:绑定普通函数

#include <iostream>
#include <functional> // std::bind 的头文件

// 定义一个普通函数
void printSum(int a, int b) {
    std::cout << "Sum: " << a + b << std::endl;
}

int main() {
    // 使用 std::bind 绑定 printSum 函数,并预先设置第一个参数为 10
    auto bindFunc = std::bind(printSum, 10, std::placeholders::_1);

    // 调用 bindFunc,只需要提供第二个参数
    bindFunc(20); // 输出:Sum: 30

    return 0;
}

代码解析

  1. std::bind(printSum, 10, std::placeholders::_1)

    • printSum 是我们要绑定的函数。
    • 10 是预先设置的第一个参数。
    • std::placeholders::_1 是一个占位符,表示生成的函数对象在调用时需要提供的第一个参数。
  2. bindFunc(20)

    • 调用生成的函数对象 bindFunc,传入参数 20
    • 10 是预先设置的参数,20 是调用时提供的参数。
    • 最终调用 printSum(10, 20),输出 Sum: 30

3. 绑定成员函数

std::bind不仅可以绑定普通函数,还可以绑定类的成员函数。绑定成员函数时,需要提供一个对象的实例。

示例2:绑定成员函数

#include <iostream>
#include <functional>

class Calculator {
public:
    void add(int a, int b) {
        std::cout << "Sum: " << a + b << std::endl;
    }
};

int main() {
    Calculator calc;

    // 使用 std::bind 绑定成员函数 add,并预先设置对象实例和第一个参数
    auto bindFunc = std::bind(&Calculator::add, &calc, 10, std::placeholders::_1);

    // 调用 bindFunc,只需要提供第二个参数
    bindFunc(20); // 输出:Sum: 30

    return 0;
}

代码解析

  1. std::bind(&Calculator::add, &calc, 10, std::placeholders::_1)

    • &Calculator::add 是成员函数指针。
    • &calc 是对象实例的指针。
    • 10 是预先设置的第一个参数。
    • std::placeholders::_1 是占位符,表示调用时需要提供的第一个参数。
  2. bindFunc(20)

    • 调用生成的函数对象 bindFunc,传入参数 20
    • 最终调用 calc.add(10, 20),输出 Sum: 30

4. 占位符的高级用法

std::bind允许我们使用占位符来灵活地调整参数的顺序。std::placeholders::_1, std::placeholders::_2, 等等,表示生成的函数对象在调用时需要提供的参数位置。

示例3:调整参数顺序

#include <iostream>
#include <functional>

void printThreeNumbers(int a, int b, int c) {
    std::cout << "Numbers: " << a << ", " << b << ", " << c << std::endl;
}

int main() {
    // 使用 std::bind 绑定 printThreeNumbers,并调整参数顺序
    auto bindFunc = std::bind(printThreeNumbers, std::placeholders::_3, std::placeholders::_1, std::placeholders::_2);

    // 调用 bindFunc,传入参数
    bindFunc(10, 20, 30); // 输出:Numbers: 30, 10, 20

    return 0;
}

代码解析

  1. std::bind(printThreeNumbers, std::placeholders::_3, std::placeholders::_1, std::placeholders::_2)

    • std::placeholders::_3 表示第三个参数。
    • std::placeholders::_1 表示第一个参数。
    • std::placeholders::_2 表示第二个参数。
  2. bindFunc(10, 20, 30)

    • 调用生成的函数对象 bindFunc,传入参数 10, 20, 30
    • 最终调用 printThreeNumbers(30, 10, 20),输出 Numbers: 30, 10, 20

5. std::bind的原理

std::bind的本质是生成一个新的可调用对象(通常是一个std::function对象),这个对象内部保存了原始的可调用对象和绑定的参数。当生成的函数对象被调用时,它会根据绑定的参数和占位符,将调用时的参数传递给原始的可调用对象。

核心知识点

  1. 可调用对象

    • 包括普通函数、函数指针、成员函数指针、函数对象(Functor)等。
  2. 占位符

    • std::placeholders::_1, std::placeholders::_2, 等等,表示生成的函数对象在调用时需要提供的参数位置。
  3. 参数绑定

    • std::bind会将绑定的参数和占位符一起保存,生成一个新的可调用对象。
  4. 返回值

    • std::bind返回一个std::function对象,可以像普通函数一样调用。

6. 进阶用法:绑定函数对象

除了普通函数和成员函数,std::bind还可以绑定函数对象(Functor)。函数对象是一个重载了operator()的类实例。

示例4:绑定函数对象

#include <iostream>
#include <functional>

class Adder {
public:
    int operator()(int a, int b) const {
        return a + b;
    }
};

int main() {
    Adder adder;

    // 使用 std::bind 绑定函数对象,并预先设置第一个参数为 10
    auto bindFunc = std::bind(adder, 10, std::placeholders::_1);

    // 调用 bindFunc,只需要提供第二个参数
    std::cout << "Sum: " << bindFunc(20) << std::endl; // 输出:Sum: 30

    return 0;
}

代码解析

  1. std::bind(adder, 10, std::placeholders::_1)

    • adder 是函数对象。
    • 10 是预先设置的第一个参数。
    • std::placeholders::_1 是占位符,表示调用时需要提供的第一个参数。
  2. bindFunc(20)

    • 调用生成的函数对象 bindFunc,传入参数 20
    • 最终调用 adder(10, 20),输出 Sum: 30

7. 总结

std::bind是C++中一个非常强大的工具,它允许我们将函数、成员函数、函数对象等与参数绑定在一起,生成一个新的可调用对象。通过占位符,我们还可以灵活地调整参数的顺序。

核心知识点回顾

  1. std::bind的基本用法:绑定普通函数、成员函数、函数对象。
  2. 占位符std::placeholders::_1, std::placeholders::_2 等,用于调整参数顺序。
  3. 原理std::bind生成一个新的可调用对象,内部保存原始的可调用对象和绑定的参数。
  4. 返回值std::bind返回一个std::function对象。

通过本文的学习,相信你已经掌握了std::bind的基本用法和原理。在实际编程中,std::bind可以帮助你简化代码,提高代码的可读性和灵活性。继续练习和探索,你会在C++编程中更加得心应手!

文章合集:chongzicbo/ReadWriteThink: 博学而笃志,切问而近思 (github.com)

个人博客:程博仕

微信公众号:

微信公众号