std::function | std::bind | lambda

c++ 使用中经常遇到函数对象、函数指针、匿名函数、参数绑定等概念,初次接触总是晕乎乎的,因此本文系统整理下他们的区别、用法。

--1 std::function

泛型函数封装器、用于存储和调用可调用对象。是不是很像函数指针的用途,其实它和函数指针的功能基本一致,只是它能支持lambda 表达式、成员函数的封装和调用,因此通用性更强。

函数指针表达式:					返回类型 (*指针名)(参数类型列表);
std::function 表达式:	std::function<返回类型(参数类型列表)>函数名

可以发现,它和lambda 和 std::bind的关系是,lambda 表达式和 std::bind 的返回值可以用std::function 去封装。

#include <iostream>
#include <functional>

int main() {
    int value = 42;
    auto lambda = [value] { return value; };

    // 将 Lambda 表达式封装到 std::function 中
    std::function<int()> func = lambda;

    // 通过 std::function 调用 Lambda 表达式
    int result = func();
    std::cout << "Result: " << result << std::endl; // 输出 "Result: 42"

    return 0;
}
#include <iostream>
#include <functional>

// 普通函数
void printMessage(const std::string& message, int repeat) {
    for (int i = 0; i < repeat; ++i) {
        std::cout << message << std::endl;
    }
}

int main() {
    // 使用 std::bind 绑定参数
    auto boundFunction = std::bind(printMessage, "Hello", std::placeholders::_1);

    // 将绑定表达式封装到 std::function 中
    std::function<void(int)> func = boundFunction;

    // 通过 std::function 调用绑定表达式
    func(3); // 输出 "Hello" 三次

    return 0;
}

--2 std::bind

表达式:std::bind(可调用对象, 参数列表...)

std::bind 是c++ 标准库中的一个函数模板,用于创建一个可调用对象,他可以将一个函数或者可调用对象的参数绑定为固定值(当绑定成员函数的时候,第一个参数可以认为是将该成员函数的this指针绑定为固定值)。

--2.1 绑定普通函数

#include <iostream>
#include <functional>

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

int main() {
    auto bound_func = std::bind(print, 10, std::placeholders::_1); // 将第一个参数绑定为 10
    bound_func(20); // 输出:10, 20
    return 0;
}

--2.2 绑定成员函数

#include <iostream>
#include <functional>

class MyClass {
public:
    void print(int a, int b) {
        std::cout << a << ", " << b << std::endl;
    }
};

int main() {
    MyClass obj;
    auto bound_member_func = std::bind(&MyClass::print, &obj, std::placeholders::_1, std::placeholders::_2);
    bound_member_func(10, 20); // 输出:10, 20
    return 0;
}

--2.3 绑定lambda表达式

#include <iostream>
#include <functional>

int main() {
    auto lambda = [](int a, int b) {
        std::cout << a << ", " << b << std::endl;
    };

    auto bound_lambda = std::bind(lambda, 10, std::placeholders::_1);
    bound_lambda(20); // 输出:10, 20
    return 0;
}

--3 lambda

用于在代码中直接定义简短的函数,捕获当前作用域的变量,语法简洁,性能更好。

[capture-list] (parameters) -> return-type { body }
#include <iostream>
#include <functional>

class MyClass {
public:
    void printMessage(const std::string& message) {
        std::cout << "Message: " << message << std::endl;
    }
};

int main() {
    MyClass obj;
    auto lambda = [&obj](const std::string& message) { obj.printMessage(message); };
    lambda("Hello from Lambda!");
    return 0;
} 

上面的例子有两个疑问?

(1)&obj 是取址吗?那传入的是指针吗?

(2)如果是指针那为什么不是 obj ->printMessage(message); ?

原因是:这里的&代表的捕获引用,而不是取地址,函数体内是obj是外部obj传入的别名对象,不是指针。

这里也可以是[&](const std::string& message) { obj.printMessage(message); }这个写法,代表捕获当前作用域中所有外部变量的引用。

原文链接:,转发请注明来源!