[C++] C++11新增
一、列表初始化
C++98:
在C++98中,标准允许使用花括号{}对数组元素进行统一的列表初始值设定。
struct Simple1
{int _a;int _b;
};//C++98
int main()
{int a1[] = { 1,2,3,4,5,6 };int a2[7] = { 0 };//本质是类型转换(构造+拷贝构造 -> 优化 直接构造)Simple1 s1 = { 1,2 };return 0;
}
C++11:
C++11扩大了用大括号括起的列表(初始化列表)的使用范围,使其可用于所有的内置类型和用户自定义的类型,使用初始化列表时,可添加等号(=),也可不添加。(列表初始化可以在{}之前使用等号,其效果与不使用=没有什么区别。)
实际是因为C++11新增了一个initializer_list,initializer_list是系统自定义的类模板,该类模板中主要有三个方法:begin()、end()迭代器以及获取区间中元素个数的方法size()。
多个对象想要支持列表初始化,只需给该类(模板类)添加一个带有initializer_list类型参数的构造函数即可。
//C++11
//一切都可以用列表初始化
int main()
{// 内置类型变量int x1 = { 1 };int x2{ 1 };int x3 = 1 + 1;int x4 = { 1 + 1 };int x5{ 1 + 1 };// 数组int arr1[5]{ 1,2,3,4,5 };int arr2[]{ 1,2,3,4,5 };// 动态数组,在C++98中不支持int* arr3 = new int[5]{ 1,2,3,4,5 };// 标准容器vector<int> v1 = { 1,2,3,4,5 };vector<int> v{ 1,2,3,4,5 };map<int, int> m1 = { {1,1}, {2,2,},{3,3},{4,4} };map<int, int> m{ {1,1}, {2,2,},{3,3},{4,4} };//标准库支持单个对象的列表初始化Simple1 s{ 1, 2 };return 0;
}
二、声明
1、auto
C++11中,可以使用auto来根据变量初始化表达式类型推导变量的实际类型,可以给程序的书写提供许多方便。将程序中it的类型换成auto,程序可以通过编译,而且更加简洁。
int main()
{map<string, string> m{ {"menu", "菜单"}, {"delete","删除"} };// 使用迭代器遍历容器, 迭代器类型太繁琐//map<string, string>::iterator it = m.begin();//使用autoauto it = m.begin();while (it != m.end()){cout << it->first << " " << it->second << endl;++it;}return 0;
}
2、decltype
auto使用的前提是:必须要对auto声明的类型进行初始化,否则编译器无法推导出auto的实际类型。但有时候可能需要根据表达式运行完成之后结果的类型进行推导,因为编译期间,代码不会运行,此时auto也就无能为力。
而decltype是根据表达式的实际类型推导出定义变量时所用的类型。这个类型可以用来做实例化模版实参或者再定义对象。
int main()
{int a = 11;float b = 10.11;auto ret = a * b;vector<decltype(ret)> v{ 12,12.12,14.1 };for (auto e : v){cout << e << endl;}return 0;
}
三、范围for
范围for在底层实际是被替换成了迭代器。
int main()
{vector<int> v{ 1,4,6,2,5,11 };for (auto e : v){cout << e << " ";}cout << endl;return 0;
}
四、智能指针
由于智能指针内容较多,请查看智能指针
五、新增容器
静态数组array
array<int,10> arr = { 1,2,3,4,5 };
forward_list
forward_list实际上就是单链表,区别于双向链表list
unordered系列
(unordered_set/unordered_map)
参考:哈希
六、右值引用
1、左值与右值:
一般认为:
- 普通类型的变量,因为有名字,可以取地址,都认为是左值。
- const修饰的常量,不可修改,只读类型的,理论应该按照右值对待,但因为其可以取地址(如果只是const类型常量的定义,编译器不给其开辟空间,如果对该常量取地址时,编译器才为其开辟空间),C++11认为其是左值。
- 如果表达式的运行结果是一个临时变量或者对象,认为是右值。
- 如果表达式运行结果或单个变量是一个引用则认为是左值。
C++11对右值进行了严格的区分:
- C语言中的纯右值,比如:a+b, 100
- 将亡值。比如:表达式的中间结果、函数按照值的方式进行返回。
2、左值引用与右值引用
左值引用:
int main()
{int* p1 = new int[10]{ 1,2,3,4,5,6,7,8,9,99 };int*& r1 = p1;int a = 1;int& r2 = a;const int& r3 = 10;return 0;
}
右值引用:
int main()
{int&& r1 = 10;int&& r2 = 1 + 3;int i = 11;int&& r3 = i + 11;int&& rr = move(i);return 0;
}
注:右值引用可以给move(左值)取别名。不过,不要轻易使用move,有时候会产生意想不到的结果。
3、移动构造/移动赋值
C++11中新增了两个默认成员函数:移动构造函数、移动赋值运算符重载。
如果我们没有实现移动构造函数,且没有实现析构函数、拷贝构造、拷贝赋值重载中的任意一个(都没有写),那么编译器会 自动生成一个默认移动构造。默认生成的移动构造函数,对于内置类型成员,会逐成员按字节拷贝,自定义类型成员,则看它是否实现了移动构造,若实现了则调用,否则调用拷贝构造。(移动赋值重载与其完全类似)
不过,在C++11中,可以在默认函数定义或者声明时加上=default,从而显式的指示编译器生成该函数的默认版本,用=default修饰的函数称为显式缺省函数。(强制编译器生成)
此外,如果能想要限制某些默认函数的生成,在C++98中,是该函数设置成private,并且不给定义,这样只要其他人想要调用就会报错。在C++11中更简单,只需在该函数声明加上=delete即可,该语法指示编译器不生成对应函数的默认版本,称=delete修饰的函数为删除函数。
C++11提出了移动语义概念,即:将一个对象中资源移动到另一个对象中。
这样就解决了 由于函数返回值的生命周期(函数返回时,一般是创建一个临时对象,用该临时对象构造接收函数返回值的变量)问题,无法使用引用返回 的问题。
而在C++11中如果需要实现移动语义,必须使用右值引用。
如:
String(String&& s)
: _str(s._str)
{s._str = nullptr;
}
注:
- 移动构造函数的参数不能设置成const类型的右值引用,因为资源无法转移而导致移动语义失效。
- 在C++11中,编译器会为类默认生成一个移动构造,该移动构造为浅拷贝,因此当类中涉及到资源管理时,用户必须显式定义自己的移动构造。
- 右值被右值引用引用后的属性是左值。因为右值不能直接修改,但是右值被右值引用后,需要被修改,否则无法实现移动构造和移动赋值。
当需要用右值引用引用一个左值时,可以通过move函数将左值转化为右值。C++11中std::move()函数位于 头文件中,该函数名字具有迷惑性,它并不搬移任何东西,唯一的功能就是将一个左值强制转化为右值引用,然后实现移动语义。
4、完美转发
完美转发:
在函数模板中,完全依照模板的参数的类型,将参数传递给函数模板中调用的另外一个函数:
函数模板在向其他函数传递自身形参时,如果相应实参是左值,它就应该被转发为左值;如果相
应实参是右值,它就应该被转发为右值。
C++11通过forward函数来实现完美转发:
void Fun(int& x)
{cout << "lvalue ref" << endl;
}void Fun(int&& x)
{ cout << "rvalue ref" << endl;
}void Fun(const int& x)
{cout << "const lvalue ref" << endl;
}void Fun(const int&& x)
{ cout << "const rvalue ref" << endl;
}template<typename T>
void PerfectForward(T&& t)
{ Fun(forward<T>(t));
}
int main()
{PerfectForward(10); // rvalue refint a;PerfectForward(a); // lvalue refPerfectForward(move(a)); // rvalue refconst int b = 8;PerfectForward(b); // const lvalue refPerfectForward(move(b)); // const rvalue refreturn 0;
}
七、可变参数模版
比如list中的emplace_back就是使用了它。
输出大小:
//Args是一个模版参数包,args是一个函数形参参数包
//声明一个模版参数包Args...args,这个参数包中可以包含0到任意个模版参数
template<class ...Args>
void show_list(Args... args)
{cout << sizeof...(args) << endl;
}int main()
{show_list(1, 1, 1);show_list('a',"aa");show_list(1.1, 'a');show_list(1, 1.1, 'a', "xx");return 0;
}
输出每个元素:
void _show_list()
{cout << endl;
}
//编译时推演
//第一个模版参数依次解析获取参数值
template<class T,class ...Args>
void _show_list(const T& val, Args ...args)
{cout << val << " ";_show_list(args...);
}template<class ...Args>
void show_list(Args... args)
{_show_list(args...);
}int main()
{show_list(1, 1, 1);show_list('a',"aa");show_list(1.1, 'a');show_list(1, 1.1, 'a', "xx");return 0;
}
八、 lambda表达式
lambda表达式解决了需要写仿函数重载operator()的问题,尤其每次比较的逻辑不一样,需要去实现多个类,特别是相同类的命名。
语法:
lambda表达式书写格式:
[capture-list] (parameters) mutable -> return-type { statement }
lambda表达式各部分说明:
- [capture-list] : 捕捉列表,该列表总是出现在lambda函数的开始位置,编译器根据[]来判断接下来的代码是否为lambda函数,捕捉列表能够捕捉上下文中的变量供lambda函数使用。
- (parameters):参数列表。与普通函数的参数列表一致,如果不需要参数传递,则可以连同()一起省略
- mutable:默认情况下,lambda函数总是一个const函数,mutable可以取消其常量性。使用该修饰符时,参数列表不可省略(即使参数为空)。
- ->returntype:返回值类型。用追踪返回类型形式声明函数的返回值类型,没有返回值时此部分可省略。返回值类型明确情况下,也可省略,由编译器对返回类型进行推导。
- {statement}:函数体。在该函数体内,除了可以使用其参数外,还可以使用所有捕获到的变量。
注意:
- 在lambda函数定义中,参数列表和返回值类型都是可选部分,而捕捉列表和函数体可以为空。因此C++11中最简单的lambda函数为:[]{}; 该lambda函数不能做任何事情。
- 捕捉列表描述了上下文中哪些数据可以被lambda使用,以及使用的方式是传值还是传引用。
[var]:表示值传递方式捕捉变量var
[=]:表示值传递方式捕获所有父作用域中的变量(包括this)
[&var]:表示引用传递捕捉变量var
[&]:表示引用传递捕捉所有父作用域中的变量(包括this)
[this]:表示值传递方式捕捉当前的this指针 - 父作用域指包含lambda函数的语句块
- 语法上捕捉列表可由多个捕捉项组成,并以逗号分割。
- 捕捉列表不允许变量重复传递,否则就会导致编译错误。
- 在块作用域以外的lambda函数捕捉列表必须为空。
- 在块作用域中的lambda函数仅能捕捉父作用域中局部变量,捕捉任何非此作用域或者非局部变量都会导致编译报错。
- lambda表达式之间不能相互赋值,即使看起来类型相同
使用:
int main()
{int a = 1;int b = 2;cout << a << " " << b << endl;auto f1 = [](int& a, int& b){int tmp = a;a = b;b = tmp;};f1(a, b);cout << a << " " << b << endl;return 0;
}
int main()
{int a = 1;int b = 2;cout << a << " " << b << endl;//通过捕捉列表,传引用auto f2 = [&a, &b] {int tmp = a;a = b;b = tmp;};f2();cout << a << " " << b << endl;return 0;
}
class Test
{
public:void func(){auto f = [=]{cout << _a << " " << _b << endl;};}private:int _a = 2;int _b = 4;
};int main()
{Test t;t.func();return 0;
}
九、包装器(适配器)
1、function
function包装器包装的是:函数指针(类型用起来反人类)、仿函数(需在全局定义)、lambda(类型对我们是匿名的)中的任意一个。
bool Comp(int& a, int& b)
{return a < b;
}struct Comps
{bool operator()(int& a, int& b){return a < b;}
};#include<functional>
#include<map>
int main()
{auto complambda = [](int& a, int& b) ->bool{return a < b;};map < string, function<bool(int&, int&)>> m{{"函数指针",Comp},{"仿函数",Comps()},{"lambda",complambda}};int x = 1;int y = 2;cout << m["函数指针"](x, y) << endl;cout << m["仿函数"](x, y) << endl;cout << m["lambda"](x, y) << endl;return 0;
}
包装成员函数:
静态成员函数(static)可以不用加“&”。
成员函数取地址比较特殊,需要加上类域和&。
struct AAA
{
public:static void A(int a){a = 0;}void AA(float a){a = 1.1;}};int main()
{function<void(int)> f1 = AAA::A;f1(1);function<void(AAA*, float)> f2 = &AAA::AA;AAA a;f2(&a, 2.2); //注意不能使用匿名对象,因为右值不可以取地址function<void(AAA, float)> f3 = &AAA::AA;f3(AAA(), 2.2);return 0;
}
2.bind
bind是一个函数模板,它就像一个函数包装器(适配器),接受一个可调用对象(callable object),生成一个新的可调用对象来“适应”原对象的参数列表。
struct AAA
{
public:static void A(int a){cout << a << endl;}void AA(float a){cout << a << endl;}};void aaa(int a, int b)
{cout << a << " " << b << endl;
}int main()
{function<void(int)> f1 = AAA::A;f1(1);function<void(AAA*, float)> f2 = &AAA::AA;AAA a;f2(&a, 2.2); //注意不能使用匿名对象,因为右值不可以取地址function<void(AAA, float)> f3 = &AAA::AA;f3(AAA(), 2.2);//调整传参顺序function<void(int, int)> ff1 = bind(aaa, placeholders::_2, placeholders::_1);ff1(3, 5);//调整参数个数function<void(int)> ff2 = bind(aaa, 22, placeholders::_1);ff2(5);function<void(float)> ff3 = bind(&AAA::AA, AAA(), placeholders::_1);ff3(100.1);return 0;
}
可以将bind函数看作是一个通用的函数适配器,它接受一个可调用对象,生成一个新的可调用对
象来“适应”原对象的参数列表。
调用bind的一般形式:auto newCallable = bind(callable,arg_list);
其中,newCallable本身是一个可调用对象,arg_list是一个逗号分隔的参数列表,对应给定的
callable的参数。当我们调用newCallable时,newCallable会调用callable,并传给它arg_list中
的参数。
arg_list中的参数可能包含形如_n的名字,其中n是一个整数,这些参数是“占位符”,表示
newCallable的参数,它们占据了传递给newCallable的参数的“位置”。数值n表示生成的可调用对
象中参数的位置:_1为newCallable的第一个参数,_2为第二个参数,以此类推。
相关文章:

[C++] C++11新增
一、列表初始化 C98: 在C98中,标准允许使用花括号{}对数组元素进行统一的列表初始值设定。 struct Simple1 {int _a;int _b; };//C98 int main() {int a1[] { 1,2,3,4,5,6 };int a2[7] { 0 };//本质是类型转换(构造拷贝构造 -> 优化 …...

802.11 wireshark 抓包
80211 wireshark 抓包 前言配置 monitor软件配置wireshark 操作 前言 本人习惯使用 Omnipeek 抓包分析,所以 wireshark 的实验只讲到抓包完成。 Windows 环境采用 wireshark 抓包是比较麻烦的,因为支持在 Windows 环境中支持抓包的网卡并不多࿰…...

vscode 调试web后端
1、调试环境配置 一、安装python环境管理器 其中要先在vscode选择对应的python环境,最方便的是按照环境管理器后从中选择。其中在【externsions】里面安装python即可。 如下: 二、编写launch.json文件 其中如下: {// Use IntelliSense …...

JAVA默写单词小程序
编写一个记单词和默写单词两个功能的小程序 package com.lu.word;import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; import lombok.ToString;Data AllArgsConstructor NoArgsConstructor ToString public class A {private String k;p…...

认知、情绪、情感、意志、人格
皮亚杰的认知发展阶段理论 个别差异与因材施教 情绪 情绪的理论 情感与情绪 意志 人格...

解析capl文件生成XML Test Module对应的xml工具
之前一直用的CAPL Test Module来写代码,所有的控制都是在MainTest()函数来实现的,但是有一次,代码都写完了,突然需要用xml的这种方式来实现,很突然,之前也没研究过,整理这个xml整的一身汗&#…...

Java中的反射是怎么回事?
反射的概念 《Java核心技术》中的定义是这样的:能够分析类能力的程序,就是反射 这就是一个概念,跟java中经常提的问题:对象是什么? 一类问题,简单来说就是将类创建对象的逻辑反过来,由对象获得…...

07 STM32寄存器开发基础-中断编程
文章目录 一、前言二、系列文章三、如何学习?四、单片机的中断知识点4.1 中断的概念4.2 中断服务函数中断服务函数与中断的关系中断服务函数的特点与编写要求中断服务函数的命名规则4.3 超声波测距项目里中断的使用思路超声波测距原理使用中断实现超声波测距硬件连接工作流程具…...

聚簇和非聚簇索引/Btree和B+tree
目录 1、聚簇(聚集)索引 (1)特点 (2)优点 (3)缺点 2、二级索引(辅助索引、非聚簇索引) 3、Btree(平衡多路查找树) 4、Btree 5…...

清华学姐熬夜肝了15天的软件测试面试题出炉(附答案)建议收藏!
一、Web自动化测试 1.Selenium中hidden或者是display = none的元素是否可以定位到? 不能,可以写JavaScript将标签中的hidden先改为0,再定位元素 2.Selenium中如何保证操作元素的成功率?也就是说如何保证我点击的元素一定是可以…...

Docker 安装指南
Docker 安装指南 文章目录 Docker 安装指南1. 卸载旧版2. 配置 Docker 的 YUM 库3. 安装 Docker4. 启动和校验5. 配置镜像加速6. 常见问题和解决方法7. 阅读和资源 Docker 是一个开源的容器化平台,能够让开发者打包应用及其依赖项到一个轻量级的、可移植的容器中。以…...

系统架构设计师 - 知识产权与标准化
知识产权与标准化 知识产权与标准化(3分)保护范围与对象 ★ ★ ★ ★法律法规 保护期限 ★ ★知识产权人确定 ★ ★ ★ ★侵权判断 ★ ★ ★ ★标准化(了解)★标准的分类标准的编号 大家好呀!我是小笙,本章…...

【Python】Facebook开源时间序列数据预测模型Prophet
文章目录 一、简介二、项目的文件解读三、Prophet类主要方法和参数3.1 主要参数3.2 主要方法 四、用法示例 一、简介 Prophet 是由 Facebook 开发的一个开源工具,用于时间序列数据的预测。它特别适用于处理具有强季节性和趋势的时间序列数据,并且对节假…...

Spring 常用的三种拦截器详解
前言 在开发过程中,我们常常使用到拦截器来处理一些逻辑。最常用的三种拦截器分别是 AOP、 Interceptor 、 Filter,但其实很多人并不知道什么时候用AOP,什么时候用Interceptor,什么时候用Filter,也不知道其拦截顺序&am…...

微前端概念
微前端作用 大型应用程序的拆分独立的前端子应用降低程序复杂性,提高开发效率 微前端能力 js隔离css隔离元素隔离生命周期预加载数据通信应用跳转多层嵌套… 微前端实现方案 IframeSingle-spaQiankunMicro-app Iframe <iframe src"https://www.examp…...

FFmpeg实战 - 解复用解码
文章目录 前置知识音视频基础概念解复用、解码的流程分析FFMPEG有8个常用库 常见音视频格式的介绍aac格式介绍h264格式介绍flv格式介绍mp4格式介绍 FFmpeg解码解封装实战数据包和数据帧(AVPacket/AVFrame)AVPacket/AVFrame的引用计数问题API介绍注意事项…...

Jmeter混合压测(2407)
一 压测需求: 电商作为服务端,至少需要满足并发量,QPS:100/s,TPS:20/s。例如场景: 电商交易中,商品图片请求量最多,电商服务端需要满足并发请求查询图片信息。各家可能会并发请求同一家电商商品、订单等内容。 二 压…...

Prometheus各类监控及监控指标和告警规则
目录 linux docker监控 linux 系统进程监控 linux 系统os监控 windows 系统os监控 配置文件&告警规则 Prometheus配置文件 node_alert.rules docker_container.rules mysql_alert.rules vmware.rules Alertmanager告警规则 consoul注册服务 Dashboard JSON…...

G120 EPos配置方案及应用场景
EPos功能就是基本定位器功能,它可计算出轴的运行特性,使轴以时间最佳的方式移动到目标位置。EPos功能主要包括:设定值 直接给定(MDI)功能、 选择程序段功能、回参考点功能、点动功能、运行到固定挡块功能。 EPos功能通过处理给定的加速度、速度和位置值生成运行特性曲线,…...

定制化爬虫管理:为企业量身打造的数据抓取方案
在数据驱动的时代,企业如何高效、安全地获取互联网上的宝贵信息?定制化爬虫管理服务应运而生,成为解锁专属数据宝藏的金钥匙。本文将深入探讨定制化爬虫管理如何为企业量身打造数据抓取方案,揭秘其在海量信息中精准捕获价值数据的…...

Javascript面试基础6【每日更新10】
Gulp gulp是前端开发过程中一种基于流的代码构建工具,是自动化项目的构建利器;它不仅能对网站资源进行优化,而且在开发过程中很多重复的任务能够使用正确的工具自动完成 Gulp的核心概念:流 流,简单来说就是建立在面向对象基础上的一种抽象的…...

CTF Web信息搜集 25000字详解
目录 前言信息收集常见信息分类域名信息whois备案CDN子域名解析记录 旁站C段服务器信息端口服务器类型数据库类型waf防火墙 网站信息备份文件备份文件常见的后缀名备份文件常见的文件名gedit备份文件vim备份文件收集方法 敏感目录CMS类型(指纹识别)探针泄…...

MSPM0G3507之电赛小车
一、前言 本文没什么技术分享,纯聊天。以下内容均为笔者的浅薄理解,有不对的地方还请多多包涵。 二、相关配置 主控单元:MSPM0G3507SPTR(48角) 编译环境:Keil5.33、5.39(推荐)都可 …...

linux运维一天一个shell命令之vmstat详解
概念 vmstat 是 Linux 系统中一个非常有用的工具,主要用于报告系统的虚拟内存、进程、CPU 活动和 IO 性能等信息。以下是对 vmstat 工具的详细解释: 基本语法 vmstat [options] [delay [count]]delay:更新的时间间隔(以秒为单…...

前端开发调试工具推荐分类整理
具体前往:前端调试工具分类整理汇总...

http协议与nginx
动态页面与静态页面的差别: (1)URL不同 静态⻚⾯链接⾥没有“?” 动态⻚⾯链接⾥包含“?” (2)后缀不同 (开发语⾔不同) 静态⻚⾯⼀般以 .html .htm .xml 为后缀 动态⻚⾯⼀般以 .php .jsp .py等为后…...

一款国外开发的高质量WordPress下载站模板主题
5play下载站是由国外站长开发的一款WordPress主题,主题简约大方,为v1.8版本, 该主题模板中包含了上千个应用,登录后台以后只需要简单的三个步骤就可以轻松发布apk文章, 我们只需要在WordPress后台中导入该主题就可以…...

Laravel为什么会成为最优雅的PHP框架
Laravel之所以成为最优雅的PHP框架之一,是因为它提供了一系列的优点,包括简洁的语法、强大的功能集、高度模块化和可扩展性、优雅的ORM、内置认证系统、丰富的社区支持和测试友好等。这些优点使得Laravel在PHP框架中脱颖而出,成为了很多开发者的首选框架。 官网:https://l…...

孤儿进程的例子
先让父进程死亡,子进程的父进程会被操作系统管理 先使用gcc编译代码, 执行代码后用 ps -p <进程号> -f 查看进程 #include <stdio.h> #include <stdlib.h> #include <sys/types.h> #include <unistd.h>int main() {pid_t pid;// 创建…...

CSS前端面试题——怎么用CSS实现一个宽高自适应的正方形?
方法一:使用 padding 方案 这种方法通过设置元素的 padding 属性来实现宽高比例相等的正方形。假设我们希望正方形的边长为相对于父容器的百分比值,比如50% .square {width: 50%; /* 可以是任意宽度,这里假设为父元素宽度的50% */padding-t…...