C++11新特性

2023-11-15

  • 1.列表初始化
  • 2. 变量类型推导
  • 3. 范围for循环
  • 4. final与override
  • 5. 智能指针
  • 6. 新增加容器---静态数组array、forward_list以及unordered系列
  • 7. 默认成员函数控制
  • 8. 右值引用
  • 9. lambda表达式
  • 10. 线程库​​​​​​​

1.列表初始化

1.1、C++98中{}的初始化问题

在C++98中,标准允许使用花括号{}对数组元素进行统一的列表初始值设定。比如:
       

int array1[] = {1,2,3,4,5};
int array2[5] = {0};

对于一些自定义的类型,却无法使用这样的初始化。比如

vector<int> v{1,2,3,4,5};

1.2、内置类型的列表初始化
 

int main()
{
// 内置类型变量
int x1 = {10};
int x2{10};
int x3 = 1+2;
int x4 = {1+2};
int x5{1+2};
// 数组
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> v{1,2,3,4,5};
map<int, int> m{{1,1}, {2,2,},{3,3},{4,4}};
return 0;
}
class Point
{
public:
Point(int x = 0, int y = 0): _x(x), _y(y)
{}
private:
int _x;
int _y;
};
int main()
{
Pointer p{ 1, 2 };
return 0;
}

1.3、自定义类型的列表初始化

    标准库支持单个对象的列表初始化
            多个对象想要支持列表初始化,需给该类(模板类)添加一个带有initializer_list类型参数的构造函数即
            可。

变量类型推导

在定义变量时,必须先给出变量的实际类型,编译器才允许定义,但有些情况下可能不知道需要实际类型怎
么给,或者类型写起来特别复杂,比如

#include <map>
#include <string>
int main()
{
    std::map<std::string, std::string> m{{"apple", "苹果"}, {"banana","香蕉"}};
    std::map<std::string, std::string>::iterator it = m.begin();
    while(it != m.end())
    {
        cout<<it->first<<" "<<it->second<<endl;
        ++it;
    }
    return 0;
}

C++11中,可以使用auto来根据变量初始化表达式类型推导变量的实际类型,可以给程序的书写提供许多方
便。将程序中c与it的类型换成auto,程序可以通过编译,而且更加简洁

decltype类型推导

auto使用的前提是:必须要对auto声明的类型进行初始化,否则编译器无法推导出auto的实际类型。但有
时候可能需要根据表达式运行完成之后结果的类型进行推导,因为编译期间,代码不会运行,此时auto也就
无能为力
 

template<class T1, class T2>
T1 Add(const T1& left, const T2& right)
{
return left + right;
}

3.范围for循环

4.final与override

由于虚函数的特性,可能会被意外进行重写,为了做到精确对虚函数重载的控制,c++11使用了override和final关键字完成对这一特性的实现.
override关键字 : 显式声明对虚函数进行重载
final关键字 : 显式终结类的继承和虚函数的重载使用

5.智能指针

 下节分享

6.新增加容器---静态数组array、forward_list以及unordered系列
 

(1)std::array
std::array 保存在栈内存中,相比堆内存中的 std::vector,我们能够灵活的访问这里面的元素,从而获得更高的性能。
std::array 会在编译时创建一个固定大小的数组,std::array 不能够被隐式的转换成指针,使用 std::array只需指定其类型和大小即可. std::array<int, 4> arr= {1,2,3,4};

(2)std::forward_list
std::forward_list 是一个列表容器,使用方法和 std::list 基本类似。
和 std::list 的双向链表的实现不同,std::forward_list 使用单向链表进行实现,提供了 O(1) 复杂度的元素插入,不支持快速随机访问(这也是链表的特点),也是标准库容器中唯一一个不提供 size() 方法的容器。当不需要双向迭代时,具有比 std::list 更高的空间利用率。

(3)无序容器unordered_map、unordered_set
C++11 引入了两组无序容器,无序容器中的元素是不进行排序的,内部通过 Hash 表实现,插入和搜索元素的平均复杂度为 O(constant)。

std::unordered_map/std::unordered_multimap
td::map使用的数据结构为二叉树,而std::unordered_map内部是哈希表的实现方式,哈希map理论上查找效率为O(1)。但在存储效率上,哈希map需要增加哈希表的内存开销。

std::unordered_set/std::unordered_multiset
std::unordered_set的数据存储结构也是哈希表的方式结构,除此之外,std::unordered_set在插入时不会自动排序,这都是std::set表现不同的地方

(4)元组std::tuple
tuple是一个固定大小的不同类型值的集合,是泛化的std::pair,其中的元素个数不再限于两个,而且功能更加丰富.
元组的使用有三个核心的函数:
std::make_tuple: 构造元组
std::get: 获得元组某个位置的值
std::tie: 元组拆包
std::tuple_cat:合并两个元组,可以通过 std::tuple_cat 来实现

7.默认成员函数控制
 

在C++中对于空类编译器会生成一些默认的成员函数,比如:构造函数、拷贝构造函数、运算符重载、析构
函数和&和const&的重载、移动构造、移动拷贝构造等函数。如果在类中显式定义了,编译器将不会重新生
成默认版本。有时候这样的规则可能被忘记,最常见的是声明了带参数的构造函数,必要时则需要定义不带
参数的版本以实例化无参的对象。而且有时编译器会生成,有时又不生成,容易造成混乱,于是C++11让程
序员可以控制是否需要编译器生成。

显式缺省函数:在C++11中,可以在默认函数定义或者声明时加上=default,从而显式的指示编译器生成该函数的默认版
本,用=default修饰的函数称为显式缺省函数
 

删除默认函数:如果能想要限制某些默认函数的生成,在C++98中,是该函数设置成private,并且不给定义,这样只要其他
人想要调用就会报错。在C++11中更简单,只需在该函数声明加上=delete即可,该语法指示编译器不生成对
应函数的默认版本,称=delete修饰的函数为删除函数

 


8.右值引用

C++98中提出了引用的概念,引用即别名,引用变量与其引用实体公共同一块内存空间,而引用的底层是通
过指针来实现的,因此使用引用,可以提高程序的可读性。

为了提高程序运行效率,C++11中引入了右值引用,右值引用也是别名,但其只能对右值引用
 

int Add(int a, int b)
{
    return a + b;
}
int main()
{
    const int&& ra = 10;
    // 引用函数返回值,返回值是一个临时变量,为右值
    int&& rRet = Add(10, 20);
    return 0;
}

1. 不能简单地通过能否放在=左侧右侧或者取地址来判断左值或者右值,要根据表达式结果或变量的性质
判断,比如上述:c常量
       2. 能得到引用的表达式一定能够作为引用,否则就用常引用

普通引用只能引用左值,不能引用右值,const引用既可引用左值,也可引用右值

C++11中右值引用:只能引用右值,一般情况不能直接引用左值

值的形式返回对象的缺陷:如果一个类中涉及到资源管理,用户必须显式提供拷贝构造、赋值运算符重载以及析构函数,否则编译器将会自动生成一个默认的,如果遇到拷贝对象或者对象之间相互赋值,就会出错。

class String
{
 public:
 String(char* str = "")
{
    if (nullptr == str)
    str = "";
    _str = new char[strlen(str) + 1];
    strcpy(_str, str);
}
String(const String& s)
    : _str(new char[strlen(s._str) + 1])
{
    strcpy(_str, s._str);
}

C++11提出了移动语义概念,即:将一个对象中资源移动到另一个对象中的方式,可以有效缓解该问题

在C++11中如果需要实现移动语义,必须使用右值引用

C++98中引用作用:因为引用是一个别名,需要用指针操作的地方,可以使用指针来代替,可以提高代码的

可读性以及安全性

C++11中右值引用主要有以下作用:

          1. 实现移动语义(移动构造与移动赋值)
                  2. 给中间临时变量取别名:
                  3. 实现完美转发
 

完美转发:是指在函数模板中,完全依照模板的参数的类型,将参数传递给函数模板中调用的另外一个函数。函数模板在向                           其他函数传递自身形参时,如果相应实参是左值,它就应该被转发为左值;如果相
                         应实参是右值,它就应该被转发为右值。这样做是为了保留在其他函数针对转发而来的参数的左右值属性进
                         行不同处理

int main()
{
    string s1("hello");
    string s2(" world");
    string s3 = s1 + s2; // s3是用s1和s2拼接完成之后的结果拷贝构造的新对象
    stirng&& s4 = s1 + s2; // s4就是s1和s2拼接完成之后结果的别名
    return 0;
}


9.lambda表达式

在C++98中,如果想要对一个数据集合中的元素进行排序,可以使用std::sort方法
       如果待排序元素为自定义类型,需要用户定义排序时的比较规则

struct Goods
{
    string _name;
    double _price;
};
struct Compare
{
        bool operator()(const Goods& gl, const Goods& gr)
    {
        return gl._price <= gr._price;
    }
};
int main()
{
    Goods gds[] = { { "苹果", 2.1 }, { "相交", 3 }, { "橙子", 2.2 }, {"菠萝", 1.5} };
    sort(gds, gds+sizeof(gds) / sizeof(gds[0]), Compare());
    return 0;
}


       随着C++语法的发展,人们开始觉得上面的写法太复杂了,每次为了实现一个algorithm算法, 都要重新去
写一个类,如果每次比较的逻辑不一样,还要去实现多个类,特别是相同类的命名,这些都给编程者带来了
极大的不便。因此,在C11语法中出现了Lambda表达式

int main()
{
    Goods gds[] = { { "苹果", 2.1 }, { "相交", 3 }, { "橙子", 2.2 }, {"菠萝", 1.5} };
    sort(gds, gds + sizeof(gds) / sizeof(gds[0]), [](const Goods& l, const Goods& r)
    ->bool
    {
        return l._price < r._price;
    });
return 0;
}


lambda表达式语法

lambda表达式书写格式:[capture-list] (parameters) mutable -> return-type { statement }

int main()
{
    // 最简单的lambda表达式, 该lambda表达式没有任何意义
        []{};
    // 省略参数列表和返回值类型,返回值类型由编译器推导为int
        int a = 3, b = 4;
        [=]{return a + 3; };
    // 省略了返回值类型,无返回值类型
        auto fun1 = [&](int c){b = a + c; };
        fun1(10)
        cout<<a<<" "<<b<<endl;
    // 各部分都很完善的lambda函数
        auto fun2 = [=, &b](int c)->int{return b += a+ c; };
        cout<<fun2(10)<<endl;
    // 复制捕捉x
        int x = 10;
        auto add_x = [x](int a) mutable { x *= 2; return a + x; };
        cout << add_x(10) << endl;
    return 0;
}


捕获列表说明
捕捉列表描述了上下文中那些数据可以被lambda使用,以及使用的方式传值还是传引用。
[var]:表示值传递方式捕捉变量var
[=]:表示值传递方式捕获所有父作用域中的变量(包括this)
[&var]:表示引用传递捕捉变量var
[&]:表示引用传递捕捉所有父作用域中的变量(包括this)
[this]:表示值传递方式捕捉当前的this指针

注意:
a. 父作用域指包含lambda函数的语句块
b. 语法上捕捉列表可由多个捕捉项组成,并以逗号分割。
比如:[=, &a, &b]:以引用传递的方式捕捉变量a和b,值传递方式捕捉其他所有变量 [&,a, this]:值
传递方式捕捉变量a和this,引用方式捕捉其他变量 c. 捕捉列表不允许变量重复传递,否则就会导致编
译错误。 比如:[=, a]:=已经以值传递方式捕捉了所有变量,捕捉a重复
d. 在块作用域以外的lambda函数捕捉列表必须为空。
e. 在块作用域中的lambda函数仅能捕捉父作用域中局部变量,捕捉任何非此作用域或者非局部变量都
会导致编译报错。
f. lambda表达式之间不能相互赋值,即使看起来类型相同

 

10.线程库

(1)std::thread
std::thread为C++11的线程类,使用方法和boost接口一样,非常方便,同时,C++11的std::thread解决了boost::thread中构成参数限制的问题,我想着都是得益于C++11的可变参数的设计风格。

(2)std::atomic
std::atomic为C++11分装的原子数据类型.
从功能上看,简单地说,原子数据类型不会发生数据竞争,能直接用在多线程中而不必我们用户对其进行添加互斥资源锁的类型。从实现上,大家可以理解为这些原子类型内部自己加了锁。

(3)std::condition_variable
std::condition_variable就像Linux下使用pthread_cond_wait和pthread_cond_signal一样,可以让线程休眠,直到被唤醒,现在在从新执行。线程等待在多线程编程中使用非常频繁,经常需要等待一些异步执行的条件的返回结果。

std::condition_variable cv;
while (!ready) cv.wait(lck); //调用cv.wait(lck)的时候,线程将进入休眠
cv.notify_all(); //休眠结束
 












 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

C++11新特性 的相关文章

  • 关于vue-cli2.9.6 使用vue-video-player,视频播放rtmp视频流error:in ./node_modules/videojs-swf/dist/video-js.swf

    我在做vue前端开发项目的时候 领导让我在别人项目的基础上进行二次开发 我将自己的页面合并至平台 我用的vue cli版本是2 6 9 然后我按照正常流程 引入vue video player video js等 然后配置playerOpt
  • 【算法/剑指Offer】请实现一个函数,用来判断一颗二叉树是不是对称的。

    题目描述 请实现一个函数 用来判断一颗二叉树是不是对称的 注意 如果一个二叉树同此二叉树的镜像是同样的 定义其为对称的 代码很简单 关键还是知道怎么样才能判断一个 二叉树是否对称 只要采用前序 中序 后序 层次遍历等任何一种遍历方法 分为先
  • 复习笔记——计算机组成原理

    2014年12月考研前一周写的笔记 放在这里 希望对其他人有帮助 写到一半时 发现这个公开课的资料挺全的 http share onlinesjtu com course view php id 3 教材 视频 ppt 还有swf
  • 简单使用Linux

    1 创建虚拟机及安装操作系统 一 打开下载好的VMware Workstation软件 二 点击 创建新的虚拟机 三 选择需要创建的虚拟机 建议选自定义 再点击下一步 四 选择系统默认兼容性并选择稍后安装 再点击下一步 五 选择Linux系
  • 互联网晚报

    腾讯回应高考生喊话马化腾 2023高考首日 在杭州十四中考点 第一科语文科目考试还没有结束 一名男生就走出了考场 面对记者采访 男生喊话马化腾 腾讯能不能把QQ空间改回老版 新版太难用了 对此 腾讯QQ在其官方微博回应称 腾讯非常重视其建议
  • golang GET http、https、代理方式

    package utils import crypto tls encoding json io ioutil log net http net url time func GET url string reply interface er
  • CentOS 构建yum本地源

    不管是为了安全起见 还是为了方便 构建本地源对于维护工作肯定会提供一些便利 1 将事先准备好的镜像文件 如 CentOS 7 x86 64 DVD 1908 iso 加载至服务器CD DVD 或虚拟机CD DVD 并将镜像文件挂载至指定的目
  • java &= ~_Java基础一

    一 1 对象 其实对象就是类的实例化 如创建一个类 车 创建一个类的对象 小汽车 而且有颜色 大小 车速等等 2 类 例如车有 小汽车 大卡车 三轮车 四驱车等等 但要用一个词概括它们 则可以统称为车 现在这个 车 就相当于 类 3 方法
  • 1489. 田忌赛马 (贪心,区间dp)

    题目 田忌赛马的故事 田忌每次输一局要付200元 赢一局获得200元 平局获得0元 问 田忌和齐王都有n匹马的情况下 最多可以获得多少元 1489 田忌赛马 AcWing题库 由于田忌赛马的故事背景 我们很快就能够想到合理的贪心策略 上等马
  • mimikatz的使用

    目录 1 远程连接使用 2 本地使用 注意 1 版本问题 2 运行权限 3 抓取范围 4 抓不到密码的解决方法 mimikatz下载链接 mimikatz是个好东西 它的功能很多 最重要的是能从 lsass exe进程中获取windows的
  • 第几个幸运数

    暴力 include
  • Vue中的验证登录状态

    Vue项目中实现用户登录及token验证 先说一下我的实现步骤 使用easy mock新建登录接口 模拟用户数据 使用axios请求登录接口 匹配账号和密码 账号密码验证后 拿到token 将token存储到sessionStorage中
  • git撤回某次commit

    假设我们已经将本地代码提交到远程分分支上 但是我们想撤回某一个commit或者是对某一个文件的修改进行撤回等操作 我们可以使用以下这几种方式 一 git reset git reset 回滚到某次提交 git reset mixed 此次提
  • 数据库系统原理------ER图转化成关系模式

    E R图转换 E R图是由实体 实体的属性和实体之间的联系三个要素组成的 将E R图转换为关系模型实际上就是要将实体 实体的属性和实体之间的联系转化为关系模式 实体集向关系模式的转换 一般转换遵循的原则 实体集的转换规则 一个实体型转换为一
  • 特网科技云服务器适合安装那些操作系统

    通过云主机 择带有预装控制面板的模板 只需单击几下即可安装 可用的操作系统模板 我们在管理虚拟服务器时使用的主要操作系统是Ubuntu Debian Windows CentOS Kali Astra Orel CentOS Communi
  • unity+vuforia+二维码识别

    Easy Code Scanner 下载地址 Easy Code Scanner v2 3 本文转载自http blog csdn net puremilk684 article details 51479245 经本人验证 可以在安卓平台
  • .NET使用MQTT通信实例

    最近项目里面需要用到MQTT 刚开始听到这个词一脸茫然 不知道是什么 最后通过自己百度整理一点资料 希望最大家有帮助 在这里需要引用MQTTnet 可在解决方案在右键单击 选择 管理解决方案的 NuGet 程序包 在 浏览 选项卡下面搜索
  • AttributeError: module ‘tensorflow‘ has no attribute ‘Session‘

    代码错误 Traceback most recent call last File D PyCharm PythonProject DRL Networking master DRL Networking master IPDPS2020
  • Real-Time Rendering——9.11 Wave Optics BRDF Models波动光学BRDF模型

    The models we have discussed in the last few sections rely on geometrical optics which treats light as propagating in ra
  • 在Linux中安装nodejs(未编译版安装方法)

    技术背景 Linux安装 nodejs 总的来说 有两种方法 第一种是安装未编译版本 然后自行编译在安装 第二种是直接安装编译版本 推荐 但作为笔记 我两种都得写 那种适合自己 自行挑选 废话不多说 我们直接上步骤 第一步 执行 wget

随机推荐

  • vue.js—定义全局变量、函数

    废话不多说 直接上代码 以便以后学习查看 一 全局变量 原理 1 单独新建一个全局变量模块文件 模块中定义一些变量初始状态 用export default 暴露出去 2 在main js中引入 并通过Vue prototype挂载到vue实
  • Fragment生命周期

    http blog csdn net forever crying article details 8238863 官网帮助文档链接 http developer Android com guide components fragments
  • WindowsFormsHost控件

    WPF和WinForms是两个不同的UI框架 都是由Microsoft创建的 WPF是WinForms的一个更现代的替代品 WinForms是第一个 NET UI框架 为了在两者之间轻松过渡 Microsoft确保WinForms控件仍然可
  • 我的编程语言经历

    Alan Perlis 说过 一种不改变你编程的思维方式的语言 不值得去学 虽然写了这么多年程序 用了这么多的语言 但我自认还没悟道编程语言如何改变我的思维方式 几天前 我需要用python来为 ledisdb 写一个客户端 我突然发现 对
  • adc读出的数据和输入电压不匹配

    1 参考电压输入有误 1 stm8和stm32 模拟电源输入的电压有问题 或者精度设置出错 导致最终电压参考有误 最终adc值出错 2 华大的芯片还多了一种可能 就是adc的参考源选择错误 可选的参考源包括内部1 5v参考 2 5v参考 外
  • 创业小记:终于开发了个有点希望的产品了

    过了3个月了 做了8个产品 有一个产品 有点起色 在7月有290刀的收入 3个月时间了 打算简单复盘一下 一个字 抄 二个字 参考 三个字 微创新 我是个典型的技术同学 我不建议跟我一样背景的人从开发自己有需求的产品开始 这是主流论调 就是
  • Java JDBC (MySQL5.7)

    文章目录 第一章 JDBC简介 1 JDBC的好处 第二章 JDBC使用 1 使用步骤 2 普通方式实现代码 3 优化为工具类 4 使用数据库连接池Druid 第三章 参考资料 第一章 JDBC简介 Java DataBase Connec
  • mysql distinct和order by 一起用时,order by的字段必须在select中

    原因 1 首先 在MySQL中 distinct 的执行顺序高于 order by 2 第二 distinct 执行时会对查询的记录进行去重 产生一张虚拟的临时表 3 第三 order by 执行时对查询的虚拟临时表进行排序 产生新的虚拟临
  • Windows下MySQL免安装版的下载与配置

    因为自己学习开发的需求 需要在本地安装MySQL数据库用来做本地测试 对于个人开发者 可以下载MySQL Community Server版本 该版本是免费的 安装和配置方法如下 MySQL Server下载地址 https dev mys
  • 算法通关村-----快速排序的原理和实现

    快速排序介绍 快速排序是一种经典高效的排序方法 是分治策略在排序上的具体体现 将一个大的待排序列分割成若干个小的有序序列 最终将各个小的有序序列合并成一个大的有序序列 快速排序的实现原理 选择一个基准值 将小于基准值的元素放在基准值左侧 大
  • 程序员疯抢的 Java 面试宝典(PDF 版)限时开源,别把大厂想的那么难,关键是你准备得如何

    Java 面试 2022 届高校毕业生规模预计 1076 万人 同比增加 167 万人 对于 22 届的同学们来说 今年下半年大规模进行的秋招是获得全职 Offer 的最重要的途径 对于程序员来说 大家都知道校招难度相对于社招来说会有所降低
  • Windows IIS服务器建站/网站配置全图文流程(新手必备!) 一条龙

    阿里ECS云服务器购买配置全教程 本文提供全图文流程 中文翻译 Chinar 坚持将简单的生活方式 带给世人 拥有更好的阅读体验 高分辨率用户请根据需求调整网页缩放比例 Chinar 心分享 心创新 助力快速完成服务器的购买 配置 以及网站
  • vite 和 webpack 优缺点对比

    Vite 和 Webpack 都是前端构建工具 它们有一些相似之处 也有一些不同之处 下面是 Vite 和 Webpack 的优缺点对比 Vite 的优点 快速的开发者体验 Vite 可以实现快速的冷启动和热更新 使开发者可以迅速地获取反馈
  • [QT编程系列-21]:基本框架 - QT常见数据结构:QString、QList、QVector、QMap、QHash、QSet、QPair详解

    目录 1 QString 2 QList 3 QVector 4 QMap 5 QHash 6 QSet 7 QPair 1 QString QString是Qt中用于存储和操作字符串的类 它提供了丰富的字符串处理方法和功能 以下是QStr
  • 基于改进SEIR模型的病毒传播动力学建模与疫情预测分析(以COVID-19新冠病毒为例,超详细,带matlab源码)

    文章目录 前言 一 数学基础知识 符号定义 二 传统SEIR模型的建立与求解 1 经典的SEIR传播动力学模型建立 2 根据经典的SEIR模型列出微分方程并求解 三 SEIR模型第一次修正 1 模型建立 2 模型求解 四 SEIR模型的第二
  • C++项目实战-makefile

    makefile简介 一个工程中的源文件不计其数 一个项目有有很多的文件 现在的项目基本都是按模块进行划分的 而这些模块存放在若干目录中 makefile中定义了一系列的规则 这些规则定义了一系列如何编译程序的操作 比如哪些文件需要编译 哪
  • 如何使用git send-email

    How to Use git send email 建议使用git send email发送补丁 更多关于发送补丁的信息请参考Community 本文介绍如何使用git send email 安装 send email 你的git可能已经安
  • PLSQL Developer设置

    PLSQL Developer设置 解决用PLSQL Developer查询时数据大小超过100M的提示问题 Tools gt Preferences gt SQL Window Maximum Result Set size 0 is u
  • error 1962

    今天电脑出了一点小毛病 报错 error 1962 No operation system found 由于很多的资料还有项目在里边存着 而且只有一个c盘 这可怎么解决 对于一个英文不好的中国人来说 这可是个麻烦事 静下心 仔细琢磨还是能够
  • C++11新特性

    1 列表初始化 2 变量类型推导 3 范围for循环 4 final与override 5 智能指针 6 新增加容器 静态数组array forward list以及unordered系列 7 默认成员函数控制 8 右值引用 9 lambd