
目录
前言
Part1. Lambda表达式捕获机制详解
Part1.1. 值捕获基础特性
Part1.2. 捕获简写语法
Part1.3. mutable关键字
Part1.4. lambda底层原理
Part2. C++11 类的六大默认成员函数
Part2.1. 六大默认函数
Part2.2. C++11规则
Part2.3. 类型分类
Part2.4. = default关键字
Part3. std::function 函数包装器
Part3.1. 作用
Part3.2. 基础语法
Part3.3. 包装类成员函数
Part3.4. 调用规则
Part3.5. 包装器与逆波兰表达式
Part4. std::bind 参数绑定工具
Part4.1. 核心能力
Part4.2. 占位符规则
Part4.3. bind 结合function处理成员函数
Part5. 结语
前言
C++11包装器,lambda表达式以及bind的知识是非常重要的。在项目实践,算法题的实现中都有所体现,我们来看看吧。
let's go!!!!!!!!
Part1. Lambda表达式捕获机制详解
Part1.1. 值捕获基础特性
int a = 0;
int b = 1;
auto f = [a, &b](int x) {
a++;
b += x;
};
//[a]:值捕获,仅拷贝外部变量,lambda内部修改的只是副本,不会影响原始变量。
//[&b]:引用捕获,直接绑定外部原始变量,内部修改会作用于外部。
//重点:同一个变量不能同时捕获两次(既值捕获又引用捕获)。
Part1.2. 捕获简写语法
<1> [=]:全部值捕获。函数体内出现的外部变量,自动以值拷贝捕获;
<2> [&]:全部引用捕获。函数体内出现的外部变量,自动以引用捕获;
<3> [=, &a, &b]:默认值捕获,单独指定a、b采用引用捕获;
<4> [&, a, b]:默认引用捕获,单独指定a、b采用值捕获。
注意:lambda不能递归。因为lambda类型无法提前声明,无法在捕获列表内引用自身。
Part1.3. mutable关键字
auto f = [a](int x) mutable {
a++;
};
//值捕获得到的成员变量,默认是const属性,不允许修改;
//添加mutable后,取消const限制,允许修改捕获的副本。
//再次强调:修改的依旧是拷贝副本,无法改变外部原始变量。
Part1.4. lambda底层原理
Lambda不是语法糖,编译器会自动生成一个匿名仿函数类:
<1> 捕获的外部变量,会变成仿函数类的成员变量;
<2> 参数列表、函数体对应仿函数的operator();
<3> 返回值类型由编译器自动推导,也可以显式-> Type指定。
Part2. C++11 类的六大默认成员函数
Part2.1. 六大默认函数
<1> 默认构造函数
<2> 拷贝构造函数
<3> 拷贝赋值运算符
<4> 移动构造函数
<5> 移动赋值运算符
<6> 析构函数
Part2.2. C++11规则
如果自己没有手动实现,编译器自动生成默认版本。
一旦手动实现其中某一个,会影响其余默认函数的隐式生成。
Part2.3. 类型分类
<1> 内置类型成员:默认构造有时会初始化;
<2> 自定义类成员:调用自身默认构造。
Part2.4. = default关键字
Person(Person&& p) = default;
//强制让编译器生成默认版本的移动构造函数,即便你已经手动编写了其他构造函数。
//补充:= delete 则是显式删除函数,禁止调用。
Part3. std::function 函数包装器
头文件:#include <functional>
Part3.1. 作用
统一包装任何可调用对象:普通函数、函数指针、lambda、仿函数、类成员函数; 提供统一的类型,能够存放在容器(map/vector)中,实现回调管理。
Part3.2. 基础语法
// 模板格式:function<返回类型(参数类型列表)>
std::function<int(int,int)> f;
// 1.包装普通函数
int add(int a,int b){return a+b;}
f = add;
// 2.包装lambda表达式
f = [](int a,int b){return a+b;};
Part3.3. 包装类成员函数
成员函数隐藏参数this,使用function包装分两种情况:
<1> 静态成员函数
静态成员不存在this,直接正常包装:
struct A{
static int fun(int a,int b){
return a-b;
}
};
std::function<int(int,int)> f = A::fun;
<2> 非静态成员函数
必须额外传入对象(对象/对象指针),对应隐式this参数:
struct A{
int fun(int a,int b){
return a-b;
}
};
A a1;
// 第一种写法:绑定对象实例
std::function<int(int,int)> f = std::bind(&A::fun, a1, _1, _2);
// 第二种:绑定对象指针
std::function<int(int,int)> f = std::bind(&A::fun, &a1, _1, _2);
参数占位符 _1、_2、_3 定义在命名空间 std::placeholders。
Part3.4. 调用规则
int res = f(10,20); 调用时传入参数,占位符_1匹配第一个实参、_2匹配第二个实参。
Part3.5. 包装器与逆波兰表达式

class Solution {
public:
int evalRPN(vector<string>& tokens) {
stack<int> aaa;
map<string,function<int(int,int)>> F={
{"+",[](int a,int b){return a+b;}},
{"-",[](int a,int b){return a-b;}},
{"/",[](int a,int b){return a/b;}},
{"*",[](int a,int b){return a*b;}}
};//将包装器与容器结合
for(int i=0;i<tokens.size();i++)
{
if(F.find(tokens[i])==F.end())
{
aaa.push(stoi(tokens[i]));
}
else
{
int a=aaa.top();
aaa.pop();
int b=aaa.top();
aaa.pop();
aaa.push(F[tokens[i]](b,a));
}
}
return aaa.top();
}
};
Part4. std::bind 参数绑定工具
头文件:#include <functional>
Part4.1. 核心能力
<1> 固定函数某些参数;
<2> 重新调整参数顺序;
<3> 配合std::function包装成员函数。
Part4.2. 占位符规则
std::placeholders::_1、_2……
//含义:代表调用bind返回的函数时,传入的第N个参数。
示例:
using namespace std::placeholders;
int sub(int a,int b){
return a – b;
}
// 固定第一个参数为100,剩余参数由调用时传入
auto sub1 = bind(sub, 100, _1);
sub1(5); // 等价 sub(100,5) → 95
// 调换参数顺序
auto sub2 = bind(sub, _2, _1);
sub2(10,5); // 等价 sub(5,10) → -5
Part4.3. bind 结合function处理成员函数
struct A{
int calc(int x,int y){
return x+y;
}
};
A obj;
// bind绑定成员函数 + 对象实例 + 占位符
function<int(int,int)> f = bind(&A::calc, obj, _1, _2);
原理: bind返回一个可调用对象; std::function可以接收该对象进行存储; 非静态成员函数依赖this,bind会捕获对象,后续调用不需要再传递实例。
Part5. 结语
这篇文章我们认识到了C++11相关知识,接下来,小编还会带来C++异常处理的知识,敬请期待~
最后,祝大家可以:春风得意马蹄疾,一日看尽长安花!
最后的最后,要是觉得本文还可以的话,可以点点赞,关注小编一波,谢谢大家!~
网硕互联帮助中心




评论前必须登录!
注册