【C++】C++11部分
目录
一、列表初始化
1.1 {}初始化
1.2 initializer_list
二、变量类型推导
2.1 auto
2.2 decltype
三、STL中一些变化
3.1 新增容器
四、lambda表达式
4.1 C++98中的一个例子
4.2 lambda表达式
4.3 函数对象与lambda表达式
五、包装器
5.1 function包装器
5.2 function 的使用方法
5.3 bind
一、列表初始化
1.1 {}初始化
C++11扩大了用大括号括起的列表(初始化列表)的使用范围,使其可用于所有的内置类型和用户自
定义的类型,使用初始化列表时,可添加等号(=),也可不添加。
int a[2]{ 1,2 };
int b{ 3 };
vector<int> c{ 4,5,6,7,8 };
1.2 initializer_list
我们能使用{}初始化,是因为initializer_list的原因,下面我们来了解一下它。

它是一个新的C++的容器,一个类模板,是一个用于初始化的工具。
举一个例子,你如何用下面的数组来初始化vector呢?
int arr[5] = { 1, 2, 3, 4 };
vector<int> v;
你可能会用下面的代码来初始化
for (int i = 0; i < 5; i++)
{
v.push_back(arr[i]);
}
但是这好像太麻烦了吧。C++11后,STL的容器都增加了新的构造函数,可以通过initializer_list来初始化容器。

vector<int> v({ 1, 2, 3, 4, 5 });
这个写法,是单参数的类型转化,因为{ 1, 2, 3, 4, 5 }整体就是一个initializer_list类型的参数
同样的,我们也可以用它来初始化map
map<string, string> m = { {"apple","苹果"}, {"banana","香蕉"}, {"pear", "梨"} };
最外层的{ }就是一个initializer_list。
它的接口也很简单
| (constructor) | 构造空 initializer_list |
| size | 返回列表大小 |
| begin | 返回迭代器的开头 |
| end | 返回迭代器的最后 |
我们也可以看出来initializer_list的本质上是一个通过迭代器访问数组的容器。当其它容器通过initializer_list构造自己时,其实就是通过迭代器遍历那个存储了节点的数组,然后把数组元素一个一个插入。
换而言之,下面这两种写法是一样的。
initializer_list<int> lt = { 1, 2, 3, 4 };
list<int> l1({ 1, 2, 3, 4 });
list<int> l2(lt.begin(), lt.end());
二、变量类型推导
2.1 auto
在C++98中auto是一个存储类型的说明符,表明变量是局部自动存储类型,但是局部域中定义局
部的变量默认就是自动存储类型,所以auto就没什么价值了。C++11中废弃auto原来的用法,将
其用于实现自动类型推断。这样要求必须进行显示初始化,让编译器将定义对象的类型设置为初
始化值的类型。
auto i = 1;//整型
auto d = 3.14;//浮点型
auto p = &i;//指针
vector<int> v;
auto it = v.begin();//迭代器
2.2 decltype
decltype可以检测一个变量的类型,并且拿这个类型去声明新的类型。比如下面这个
int i = 0;
decltype(i) x = 5;
decltype(i)检测出i的类型为int,于是decltype(i)整体就变成int,从而定义出一个新的变量x。
三、STL中一些变化
3.1 新增容器
用橘色圈起来是C++11中的一些几个新容器。但最有用的是unordered_map、unordered_set。

四、lambda表达式
4.1 C++98中的一个例子
函数对象,又称为仿函数,即可以想函数一样使用的对象,就是在类中重载了operator()运算符的
类对象。
在C++98中,如果想要对一个结构体进行排序,就需要用户自己写仿函数。
struct Goods
{string _name; // 名字double _price; // 价格int _evaluate; // 评价Goods(const char* str, double price, int evaluate):_name(str), _price(price), _evaluate(evaluate){}
};
如果我们想要按照价格排序
struct ComparePriceLess
{bool operator()(const Goods& gl, const Goods& gr){return gl._price < gr._price;}
};struct ComparePriceGreater
{bool operator()(const Goods& gl, const Goods& gr){return gl._price > gr._price;}
};
随着C++语法的发展,人们开始觉得上面的写法太复杂了,每次为了实现一个algorithm算法,
都要重新去写一个类,如果每次比较的逻辑不一样,还要去实现多个类,特别是相同类的命名,
这些都给编程者带来了极大的不便。因此,在C++11语法中出现了Lambda表达式。
4.2 lambda表达式
lambda表达式书写格式:
[capture_list] (parameters) mutable -> return_type {statement}
我们来看看各部分是做什么的
[capture_list]:捕捉列表。编译器根据[]来判断接下来的代码是否为lambda函数,捕捉列表能够捕捉上下文中的变量供lambda函数使用(parameters):参数列表。普通函数的参数列表一致。如果不需要参数传递,则可以
连同()一起省略mutable:一个关键字。mutable可以取消其常量性。使用该修饰符时,参数列表不可省略-> return_type:返回值类型。用追踪返回类型形式声明函数的返回值类型,返回值类型明确情况下,可省略,由编译器对返回类型进行推导。没有返回值时此部分也可省略{statement}: 函数体。在该函数体内,除了可以使用其参数外,还可以使用所有捕获
到的变量
举一个例子,下面是一个完整的lambda表达式。
auto add = [](int a, int b)mutable -> int { return a + b; };
当然我们也可以将其省略成下面这个式子
auto add = [](int a, int b) { return a + b; };
那lambda表达式有什么作用呢?答案是:lambda会返回一个仿函数对象
比如我们上面写的例子,其实add就是一个仿函数对象了,我们可以直接按照调用函数的方式来调用这个仿函数:add(1, 2);。但是要注意, lambda表达式实际上可以理解为无名函数,该函数无法直接调用,如果想要直接调用,因此必须使用auto来接受这个仿函数对象。
下面我们再来详细地讲一讲lambda表达式最前面的[]的作用。
[]描述了上下文中那些数据可以被lambda使用,以及使用的方式是传值还是传引用。
- [var]:表示值传递方式捕捉变量var
- [=]:表示值传递方式捕获所有父作用域中的变量(包括this)
- [&var]:表示引用传递捕捉变量var
- [&]:表示引用传递捕捉所有父作用域中的变量(包括this)
- [this]:表示值传递方式捕捉当前的this指针
举几个例子解释一下。
int x = 1;
int y = 2;/*如果直接通过变量名捕获,此时是传值调用,修改函数体内部的变量,不会影响父作用域的变量*/
auto add = [x, y] {return x + y; };
/*通过直接传值捕获的变量,自带const属性,不允许修改。此时代码就会报错*/
/*auto add = [x, y]
{
x += 5;
y += 5;
};*//*mutable可以让被捕获的参数可以修改。需要注意的是如果使用了mutable,()不可省略*/
auto add = [x, y] () mutable
{
x += 5;
y += 5;
};
/*以传引用的方式来捕获变量,此时修改函数内部的x和y,就是在修改父作用域的x和y。如果使用了传引用捕获变量,就算没有mutable也可以修改参数*/auto add = [&x, &y]
{
x += 5;
y += 5;
};
/*[=]是以传值的形式捕获父作用域所有变量,[&]是以传引用的形式捕获父作用域所有变量*/
auto add = [=]
{
return x + y;
};
auto add = [&]
{
return x + y;
};/*
我们还可以把传值和传引用混合使用,让部分参数传参,部分参数传引用。
[x, &y]:以传值的形式捕获x,以传引用的形式捕获y
[=, &x]:以传值的形式捕获父作用域所有变量,以传引用的形式捕获x
[&, x]:以传值的形式捕获x,以传引用的形式捕获父作用域所有变量*/
有了lambda表达式之后,我们就可以改变一下最开始的排序了
vector<Goods> v = { { "苹果", 2.1, 5 }, { "香蕉", 3, 4 }, { "橙子", 2.2, 3 }, { "菠萝", 1.5, 4 } };sort(v.begin(), v.end(), [](const Goods& g1, const Goods& g2) {return g1._price < g2._price; });sort(v.begin(), v.end(), [](const Goods& g1, const Goods& g2) {return g1._price > g2._price; });
4.3 函数对象与lambda表达式
从使用方式上来看,函数对象与lambda表达式完全一样。
函数对象将rate作为其成员变量,在定义对象时给出初始值即可,lambda表达式通过捕获列表可
以直接将该变量捕获到。

实际在底层编译器对于lambda表达式的处理方式,完全就是按照函数对象的方式处理的,即:如
果定义了一个lambda表达式,编译器会自动生成一个类,在该类中重载了operator()。
五、包装器
当我们在寄快递的时候,快递会被包装,这样我们就可以统一的在上面贴上快递信息,随后以统一的形式管理所有快递。包装器也是如此,包装器可以将具有相似属性的东西包装起来成为一个整体。
5.1 function包装器
function包装器,也叫作适配器。C++中的function本质是一个类模板,也是一个包装器。
那么我们在什么时候会用到包装器呢?我们一步步来看
我们首先回忆一下我们知道的可调用对象
- 函数指针
- 仿函数实例化出的对象
- lambda表达式
但是它们都有各自的缺点
函数指针:类型复杂,不好用
仿函数实例化出的对象:哪怕参数返回值都相同,仿函数之间的类型也不同
lambda表达式:类型是随机的,必须用auto接收
可以看到,这三者都有类型方面的大问题,我们也没有一种方式可以把所有参数类型和返回值类型相同的函数,统一的管理起来,让它们都变成一个类型?这个时候就用到包装器了。
std::function在头文件<functional>
// 类模板原型如下
template <class T> function; // undefined
template <class Ret, class... Args>
class function<Ret(Args...)>;
模板参数说明:
Ret: 被调用函数的返回类型
Args…:被调用函数的形参
function包装器,只要是返回值和参数列表都相同的可调用对象,经过这一层封装,都会变成相同的类型。
举一个例子
double func(double x)
{
return x / 2;
}struct Functor
{
double operator()(double x)
{
return x / 3;
}
};int main()
{
auto lambadaFunc = [](double d) {return d / 4; };/*func,Functor,lambadaFunc 。它们的返回值都是double,参数类型也是double,因此可以经过包装器包装为function<double<double>>*/
/*现在三者的类型就都是function<double(double)>*/
function<double(double)> func1 = func;
function<double(double)> func2 = Functor();
function<double(double)> func3 = lambadaFunc;return 0;
}
5.2 function 的使用方法
// 使用方法如下:
#include <functional>
int f(int a, int b)
{
return a + b;
}
struct Functor
{
public:
int operator() (int a, int b)
{
return a + b;
}
};class Plus
{
public:
static int plusi(int a, int b)
{
return a + b;
}
double plusd(double a, double b)
{
return a + b;
}};
int main()
{
// 函数名(函数指针)
std::function<int(int, int)> func1 = f;
cout << func1(1, 2) << endl;
// 函数对象
std::function<int(int, int)> func2 = Functor();
cout << func2(1, 2) << endl;
// lamber表达式
std::function<int(int, int)> func3 = [](const int a, const int b)
{return a + b; };
cout << func3(1, 2) << endl;
// 类的成员函数
std::function<int(int, int)> func4 = &Plus::plusi;
cout << func4(1, 2) << endl;
std::function<double(Plus, double, double)> func5 = &Plus::plusd;
cout << func5(Plus(), 1.1, 2.2) << endl;
return 0;
}
5.3 bind
bind函数
- 是一个函数模板
- 其接收多个参数,第一个参数为可调用对象,后续参数为该可调用对象的参数
- 其主要有两个功能:改变参数顺序,给指定参数绑定固定值
C++11后新增一个命名空间域placeholders,其内部会存储很多变量,这些变量用于函数的传参,变量的名字为_x表示第x个参数。
举个例子
int sub(int a, int b)
{
return a - b;
}int main()
{/*sub这个参数是一个可调用对象。
placeholders::_2表示第二个参数,placeholders::_1表示第一个参数*/
auto f1 = bind(sub, placeholders::_2, placeholders::_1);/*f1最后拿到了这个bind封装的函数,那么f1(3, 5)执行的并不是3 - 5,而是5 - 3*/
f1(3, 5);
return 0;
}
int sub(int a, int b)
{
return a - b;
}int main()
{/*第一个参数为可调用对象sub,第二个参数是一个固定值3.14,参数a都固定为3.14*/
auto f2 = bind(sub, 3.14, placeholders::_1);f2(10);//3.14 - 10
return 0;
}
bind 函数还可以用来处理函数的返回值
int add(int x, int y) {
return x + y;
}int main() {
// 绑定 add 函数,并将返回值乘以 2
auto doubleAdd = bind([](int result) { return result * 2; }, add(placeholders::_1,placeholders::_2));
int result = doubleAdd(3, 4);
cout << result << endl; // 输出 14
return 0;
}
相关文章:
【C++】C++11部分
目录 一、列表初始化 1.1 {}初始化 1.2 initializer_list 二、变量类型推导 2.1 auto 2.2 decltype 三、STL中一些变化 3.1 新增容器 四、lambda表达式 4.1 C98中的一个例子 4.2 lambda表达式 4.3 函数对象与lambda表达式 五、包装器 5.1 function包装器 5.2 fu…...
【分布式】聊聊分布式id实现方案和生产经验
对于分布式Id来说,在面试过程中也是高频面试题,所以主要针对分布式id实现方案进行详细分析下。 应用场景 对于无论是单机还是分布式系统来说,对于很多场景需要全局唯一ID, 数据库id唯一性日志traceId 可以方便找到日志链&#…...
[MERN] 使用 socket.io 实现即时通信功能
[MERN] 使用 socket.io 实现即时通信功能 效果实现如下: MERN-socket.io 实现即时聊天 Github 项目地址:https://github.com/GoldenaArcher/messenger-mern 项目使用了 MERN(MongoDB, Express, React, Node.js) socket.io 实现即时通信功能,并且使用了…...
c#面试题整理6
1.String类能否被继承,为什么 可以看到String类的修饰符是sealed,即是密封类,故不可被继承 2.一个对象的方法是否只能由一个线程访问 不是,但是可通过同步机制,确保同一个时间只有一个线程访问 3.计算2*8ÿ…...
简洁实用的3个免费wordpress主题
高端大气动态炫酷的免费企业官网wordpress主题 非常简洁的免费wordpress主题,安装简单、设置简单,几分钟就可以搭建好一个wordpress网站。 经典风格的免费wordpress主题 免费下载 https://www.fuyefa.com/wordpress...
Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
一:背景 1. 讲故事 前面跟大家分享过一篇 C# 调用 C代码引发非托管内存泄露 的文章,这是一个故意引发的正向泄露,这一篇我们从逆向的角度去洞察引发泄露的祸根代码,这东西如果在 windows 上还是很好处理的,很多人知道…...
【HDLbits--counter】
HDLbits--counter 在IC设计中,counter是十分普遍和重要的设计内容; 题目:基础计数器 module top_module (input clk,input reset,output [9:0] q);always (posedge clk) beginif(reset) beginq < 0;end else beginif(q999) beginq < 0…...
nvm 让 Node.js 版本切换更灵活
有很多小伙伴前端开发进程中,我们常常会遇到不同项目依赖不同版本 Node.js 的情况。我们不可能去卸载重新安装适应的版本去安装依赖或者启动项目。为了避免版本冲突带来的一系列麻烦,在这里给大家推荐一款Node.js 版本管理工具——nvm(Node V…...
双向选择排序算法
一 概述 双向选择排序(又称鸡尾酒选择排序)是选择排序的优化版本,核心改进在于每轮遍历同时确定未排序部分的最小值和最大值,分别交换到序列两端,从而减少遍历轮数。 二 时间复杂度 时间复杂度为(O(n^2)),但实际比较次数约为标准选择排序的 (1/2)。 三 C++实现代…...
美畅物联丨P2P系列之STUN服务器:助力网络穿透
在当今WebRTC等实时通信应用广泛兴起的复杂网络环境下,如何在NAT(网络地址转换)环境中实现高效、稳定的点对点(P2P)连接成为关键。STUN(Session Traversal Utilities for NAT)服务器作为应对这一…...
基于SpringBoot的“积分制零食自选销售平台”的设计与实现(源码+数据库+文档+PPT)
基于SpringBoot的“积分制零食自选销售平台”的设计与实现(源码数据库文档PPT) 开发语言:Java 数据库:MySQL 技术:SpringBoot 工具:IDEA/Ecilpse、Navicat、Maven 系统展示 系统总体结构图 局部E-R图 系统首页界面…...
DeepSeek-V3 技术报告解读
DeepSeek火了有一段时间了,春节假期因为没时间,所以关于deepseek大模型一系列的技术报告一直没看,新年开工后,抽一点时间把之前的坑补起来,关于DeepSeek-V3技术报告的解读已经有很多了,但我相信不同的人去读…...
Spring使用@Scheduled注解的参数详解
在现代Java开发中,定时任务是一个常见的需求。Spring框架提供了Scheduled注解,让我们能够以简单、直观的方式定义和管理这些定时任务。接下来,我们来深入探讨这个注解的使用,以及它的参数都有哪些含义和作用。 Scheduled注解可以…...
力扣72题编辑距离
题目 原理 三个操作对应的操作次数分别是: 插入:在原本的次数上 1删除:在原本的次数上1替换:如果两个位置的字符串一样,则等于原本的次数, 如果不等,在原本的次数上1 去三者的最小值,就是最小的编辑次数 示例 代码 答案是2 package org.example;public class _72_编辑距离 {pu…...
聊天服务器分布式改造
目前的聊天室是单节点的,无论是http接口还是socket接口都在同一个进程,无法承受太多人同时在线,容灾性也非常差。因此,一个成熟的IM产品一定是做成分布式的,根据功能分模块,每个模块也使用多个节点并行部署…...
Python编程中常见的10个案例
文章目录 1. Hello, World!2. 计算斐波那契数列3. 文件读写4. 列表推导式5. 异常处理6. 函数定义与调用7. 类和对象8. 使用模块9. 网络请求10. 数据可视化总结 1. Hello, World! 这是学习任何编程语言时的第一个程序。 代码示例 print("Hello, World!")2. 计算斐波…...
Ardupilot开源无人机之Geek SDK进展2025Q1
Ardupilot开源无人机之Geek SDK进展2025Q1 1. 源由2. 内容汇总2.1 【jetson-fpv】YOLO INT8 coco8 dataset 精度降级2.2 【OpenIPC-Configurator】OpenIPC Configurator 固件升级失败2.3 【OpenIPC-Adaptive-link】OpenIPC RF信号质量相关显示2.4 【OpenIPC-msposd】.srt/.osd…...
linux上安装redis[从0到1]
redis安装步骤 1.下载redis2.新建redis文件夹3.解压安装Redis4.编译5.修改相关配置6.错误 redis下载官网: https://download.redis.io/releases/ 找到自己需要的版本 1.下载redis 选着自己需要下载的版本后,右击选择复制链接,然后利用命令进行下载&am…...
批量删除 Excel 中的空白行、空白列以及空白表格
我们经常会碰到需要删除 Excel 文档表格中的空白行及空白列的场景,有一些空白行或空白列可能我们人工不好识别,因此删除空白行空白列对我们来讲就非常的繁琐,因为我们需要先识别哪些 Excel 文档中包含空白行或者空白列,我们才能够…...
MyBatis SQL 映射文件的作用和结构
MyBatis SQL 映射文件定义了 SQL 语句以及如何将 SQL 语句的参数和结果映射到 Java 对象。 一、 作用 (Purpose) MyBatis SQL 映射文件(通常命名为 XXXMapper.xml)的主要作用是: 定义 SQL 语句: 在 XML 映射文件中编写 SQL 语句…...
MYSQL之创建数据库和表
创建数据库db_ck (下面的创建是最好的创建方法,如果数据库存在也不会报错,并且指定使用utf8mb4) show databases命令可以查看所有的数据库名,可以找到刚刚创建的db_ck数据库 使用该数据库时,发现里面没有…...
react+ts+eslint+prettier 配置教程
1.创建项目 npx create-react-app my-app --template typescript 2.安装依赖 eslint:核心代码质量工具。 prettier:代码格式化工具。 eslint-plugin-prettier:将 Prettier 的规则集成到 ESLint 中。 eslint-config-prettier:…...
ArduPilot开源代码之AP_OSD
ArduPilot开源代码之AP_OSD 1. 源由2. 简介3. 补丁4. 框架设计4.1 启动代码 (AP_OSD::init)4.2 任务代码 (AP_OSD::osd_thread)4.3 实例初始化 (AP_OSD::init_backend) 5. 重要例程5.1 AP_OSD::update_stats5.2 AP_OSD::update_current_screen5.3 AP_OSD::update_osd 6. 总结7.…...
sysbench手动测试OceanBase v4.2.4集群
环境: 1、ocp(sysbench节点) 192.192.103.128 2、ob集群1-1-1 observer 192.192.103.125、192.192.103.126、192.192.103.127,primary_zone:random haproxy 192.192.103.125、192.192.103.126、192.192.103.127 一、安装sysben…...
腾讯元宝:AI 时代的快速论文阅读助手
1. 背景与需求 在 AI 研究领域,每天都会涌现大量学术论文。如何高效阅读并提取关键信息成为研究者的一大难题。腾讯元宝是腾讯推出的一款大模型,结合了**大语言模型(LLM)和自然语言处理(NLP)**技术&#x…...
重构谷粒商城09:人人开源框架的快速入门
谷粒商城09——人人开源框架的快速入门 前言:这个系列将使用最前沿的cursor作为辅助编程工具,来快速开发一些基础的编程项目。目的是为了在真实项目中,帮助初级程序员快速进阶,以最快的速度,效率,快速进阶…...
AAA 技术详解:认证、授权与计费的原理、应用与配置实践
AAA(Authentication, Authorization, Accounting,即认证、授权和计费)是网络安全的“身份管理员”,负责验证用户身份、分配访问权限并记录行为轨迹。它如同网络世界中的“物业管理系统”,通过三重机制确保接入安全、权…...
OneM2M:全球性的物联网标准-可应用于物联网中
OneM2M 是一个全球性的物联网(IoT)标准,旨在为物联网设备和服务提供统一的框架和接口,以实现设备之间的互操作性、数据共享和服务集成。OneM2M 由多个国际标准化组织(如 ETSI、TIA、TTC、ARIB 等)共同制定,目标是解决物联网领域的碎片化问题,提供一个通用的标准,支持跨…...
redis数据迁移教程(使用RedisShake实现不停机迁移十分便捷)
1.我的场景 需要把本地的redis数据上传到阿里云服务器上面,服务器上redis并没有开aof持久化,但是将rdb文件上传至服务器后每次重启redis,rdb文件会被覆盖导致无法同同步数据,最终决定使用RedisShake 2.RedisShake介绍 什么是 RedisShake RedisShake 是一个用于处理和迁移…...
Linux基本操作指令3
1、wget: 这是一个用于从网络上下载文件的命令行工具。它支持 HTTP、HTTPS 和 FTP 协议。 wget http://download.qt.io/archive/qt/5.12/5.12.9/qt-opensource-linux-x64-5.12.9.run 2、下载完成后,你可以通过以下命令使文件可执行并运行安装程序: ch…...
