深入解析C++11 lambda表达式/包装器/线程库
C++11 lambda表达式
Lambda表达式是C++11中最重要的新特性之一。Lambda表达式提供了一种简单且易于使用的方式,用于定义和传递匿名的、可调用的代码块。
基本语法
Lambda表达式的基本语法如下:
[capture list] (params) -> return_type {
// 函数体
}
上述语法中,capture list表示对外部变量的引用捕获方式;params表示形式参数列表;return_type表示返回值类型;函数体则是具体的语句块。
捕获外部变量
在Lambda表达式中,可以通过捕获外部变量来引用外部作用域中的变量。捕获外部变量的方式有两种:按值捕获和按引用捕获。
按值捕获:
int x = 10;
auto f = [x] () {
std::cout << x << std::endl; // 输出 10
};
按引用捕获:
int x = 10;
auto f = [&x] () {
std::cout << x << std::endl; // 输出 10
};
示例
#include <iostream>
int main()
{
int a = 10, b = 5;
auto f = [a, &b] (int c) -> int {
b++;
return a + b + c;
};
std::cout << f(3) << std::endl; // 输出 19
std::cout << b << std::endl; // 输出 6
return 0;
}
上述代码中,Lambda表达式f捕获了变量a和b。a被按值捕获,b被按引用捕获。在函数体中,Lambda表达式修改了b的值,但没有修改a的值。
C++11 包装器
C++11中提供了一些包装器,用于封装常见的数据结构和算法,使其具有更加通用、灵活的特性。
std::function
std::function是一个通用的函数封装器,可以用于存储任何可调用的对象(函数、函数指针、仿函数、Lambda表达式等)。
#include <iostream>
#include <functional>
using namespace std::placeholders;
int add(int a, int b)
{
return a + b;
}
int main()
{
std::function<int(int, int)> f;
f = add;
std::cout << f(2, 3) << std::endl; // 输出 5
f = [](int a, int b) {
return a * b;
};
std::cout << f(2, 3) << std::endl; // 输出 6
return 0;
}
上述代码中,std::function对象f可以存储add函数和Lambda表达式,并可以像调用普通函数一样调用它们。
std::bind
std::bind是一个通用的函数适配器,可以将一个可调用对象(函数、函数指针、成员函数等)和其参数绑定,生成一个新的可调用对象。
#include <iostream>
#include <functional>
using namespace std::placeholders;
int add(int a, int b)
{
return a + b;
}
class Calculator
{
public:
int sub(int a, int b) const
{
return a - b;
}
};
int main()
{
std::function<int(int)> f;
f = std::bind(add, _1, 2);
std::cout << f(3) << std::endl; // 输出 5
Calculator calc;
f = std::bind(&Calculator::sub, &calc, _1, 2);
std::cout << f(3) << std::endl; // 输出 1
return 0;
}
上述代码中,std::bind生成了两个新的可调用对象,其中第一个绑定add函数的第一个参数为_1,第二个参数为2;第二个绑定了Calculator类的sub成员函数和一个Calculator对象,并将第一个参数绑定为_1,第二个参数绑定为2。
C++11 线程库
C++11中提供了一个全新的线程库,该库提供了一种简单、高效和跨平台的方式,用于管理多线程应用程序。
std::thread
std::thread是C++11中的线程类,可以用于创建一个新的线程。
#include <iostream>
#include <thread>
void work(int x)
{
for (int i = 0; i < 5; i++) {
std::cout << "Working thread #" << x << " is running..." << std::endl;
std::this_thread::sleep_for(std::chrono::seconds(1));
}
}
int main()
{
std::thread t1(work, 1);
std::thread t2(work, 2);
t1.join();
t2.join();
return 0;
}
上述代码中,创建了两个新的线程t1和t2,并将一个work函数分别作为它们的执行体。每个线程在循环中输出一条消息,然后调用std::this_thread::sleep_for函数暂停1秒。
std::async
std::async是C++11中的异步函数调用机制,可以用于在后台启动一个新的线程执行指定的函数,并且可以返回一个std::future对象,表示该函数的返回值。
#include <iostream>
#include <future>
int work(int x)
{
std::cout << "Working thread #" << x << " is running..." << std::endl;
std::this_thread::sleep_for(std::chrono::seconds(3));
return x * 2;
}
int main()
{
std::future<int> f1 = std::async(std::launch::async, work, 1);
std::future<int> f2 = std::async(std::launch::async, work, 2);
std::cout << "Result1 = " << f1.get() << std::endl;
std::cout << "Result2 = " << f2.get() << std::endl;
return 0;
}
上述代码中,std::async函数使用std::launch::async标志启动了两个新的线程,并将work函数分别作为它们的执行体。每个线程输出一条消息,然后暂停3秒并返回一个整数值。最后,我们使用std::future对象获得了这两个返回值,并将它们打印出来。
结论
本文深入解析了C++11 lambda表达式、包装器和线程库三个新特性,并提供了相应的示例说明。这三个特性大大提高了C++的灵活性和效率,让我们能够更加容易地编写高性能、高可靠性的多线程程序。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:深入解析C++11 lambda表达式/包装器/线程库 - Python技术站