【C++11】【函数式编程】C++11函数式编程特性

文章目录

    • C++11函数式编程特性
    • Lambda 表达式
    • std::function
    • std::bind
    • std::transform
    • std::accumulate

C++11函数式编程特性

  1. Lambda表达式:Lambda表达式是一种匿名函数,可以在代码中直接定义和使用。它可以捕获外部变量,并且可以作为函数参数或返回值使用。

  2. std::function:std::function是一个通用的函数封装器,可以存储、复制和调用任何可调用对象,包括函数、函数指针、成员函数指针和Lambda表达式等。

  3. std::bind:std::bind是一个函数适配器,可以将一个可调用对象和一些参数绑定在一起,生成一个新的可调用对象。

  4. std::transform:std::transform是一个函数模板,可以对一个序列中的每个元素应用一个函数,并将结果存储到另一个序列中。

  5. std::accumulate:std::accumulate是一个函数模板,可以对一个序列中的所有元素进行累加或累积操作。

这些特性使得C++11更加适合函数式编程,可以更方便地使用函数式编程的思想和技巧来解决问题。

Lambda 表达式

已在其他篇章中详细描述。

std::function

std::function 是一个通用的函数封装器,可以存储、复制和调用任何可调用对象,包括函数、函数指针、成员函数指针和 Lambda 表达式等。下面是 std::function 的使用示例:

#include 
#include 

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

int main() {
    std::function<int(int, int)> func = add; // 将函数指针赋值给 std::function 对象
    std::cout << func(1, 2) << std::endl; // 输出 3

    auto lambda = [](int a, int b) -> int { return a * b; }; // 定义一个 Lambda 表达式
    func = lambda; // 将 Lambda 表达式赋值给 std::function 对象
    std::cout << func(3, 4) << std::endl; // 输出 12

    return 0;
}

在上面的示例中,我们首先定义了一个函数 add,然后将它的函数指针赋值给了一个 std::function 对象 func。接着,我们定义了一个 Lambda 表达式 lambda,并将它赋值给了 func。最后,我们调用 func 并输出结果。

需要注意的是,std::function 对象的模板参数是函数的签名,即函数的返回值类型和参数类型。在上面的示例中,std::function 表示一个返回值为 int,有两个 int 类型参数的函数。

std::bind

std::bind 是一个函数适配器,可以将一个可调用对象和一些参数绑定在一起,生成一个新的可调用对象。下面是 std::bind 的使用示例:

#include 
#include 

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

int main() {
    auto f1 = std::bind(print, 1, 2, 3); // 绑定函数和参数
    f1(); // 输出 1 2 3

    auto f2 = std::bind(print, std::placeholders::_1, std::placeholders::_2, 4); // 绑定函数和部分参数
    f2(5, 6); // 输出 5 6 4

    auto f3 = std::bind(print, std::placeholders::_2, std::placeholders::_1, std::placeholders::_3); // 绑定函数和参数,但是交换了参数的顺序
    f3(7, 8, 9); // 输出 8 7 9

    return 0;
}

在上面的示例中,我们首先定义了一个函数 print,它接受三个 int 类型的参数,并将它们输出到标准输出流中。接着,我们使用 std::bind 函数将 print 函数和一些参数绑定在一起,生成了三个新的可调用对象 f1f2f3。其中,f1 绑定了 print 函数和三个参数,f2 绑定了 print 函数和两个参数,其中第三个参数使用了占位符 std::placeholders::_1std::placeholders::_2,表示在调用 f2 时需要传入两个 int 类型的参数,而第三个参数已经被绑定为 4f3 绑定了 print 函数和三个参数,但是交换了第一个和第二个参数的顺序。

最后,我们调用了这三个可调用对象,并输出了它们的结果。需要注意的是,std::bind 函数返回的是一个可调用对象,需要使用函数调用运算符 () 来调用它。

std::transform

std::transform 是一个函数模板,可以对一个序列中的每个元素应用一个函数,并将结果存储到另一个序列中。下面是 std::transform 的使用示例:

#include 
#include 
#include 

int square(int x) {
    return x * x;
}

int main() {
    std::vector<int> v1 = {1, 2, 3, 4, 5};
    std::vector<int> v2(v1.size());

    std::transform(v1.begin(), v1.end(), v2.begin(), square); // 对 v1 中的每个元素应用 square 函数,并将结果存储到 v2 中

    for (auto x : v2) {
        std::cout << x << " ";
    }
    std::cout << std::endl; // 输出 1 4 9 16 25

    return 0;
}

在上面的示例中,我们首先定义了一个函数 square,它接受一个 int 类型的参数,并返回它的平方。接着,我们定义了一个 std::vector 对象 v1,并初始化它的元素为 {1, 2, 3, 4, 5}。然后,我们定义了另一个 std::vector 对象 v2,并使用 std::transform 函数对 v1 中的每个元素应用 square 函数,并将结果存储到 v2 中。最后,我们遍历 v2 中的元素,并输出它们的值。

需要注意的是,std::transform 函数的前两个参数是输入序列的起始和终止迭代器,第三个参数是输出序列的起始迭代器,第四个参数是一个可调用对象,用于对输入序列中的每个元素进行操作。在上面的示例中,我们使用了函数指针 square 作为可调用对象。

std::accumulate

std::accumulate 是一个函数模板,可以对一个序列中的所有元素进行累加或累积操作。下面是 std::accumulate 的使用示例:

#include 
#include 
#include 

int main() {
    std::vector<int> v = {1, 2, 3, 4, 5};
    int sum = std::accumulate(v.begin(), v.end(), 0); // 对 v 中的所有元素进行累加操作,初始值为 0

    std::cout << sum << std::endl; // 输出 15

    return 0;
}

在上面的示例中,我们定义了一个 std::vector 对象 v,并初始化它的元素为 {1, 2, 3, 4, 5}。然后,我们使用 std::accumulate 函数对 v 中的所有元素进行累加操作,并将结果存储到变量 sum 中。最后,我们输出 sum 的值。

需要注意的是,std::accumulate 函数的前两个参数是输入序列的起始和终止迭代器,第三个参数是累加的初始值。在上面的示例中,我们将初始值设为 0,表示从 0 开始累加。如果输入序列中的元素类型不是整数类型,需要提供一个自定义的累加函数作为第四个参数。

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