C++11新增加了哪些新特性?一般而言,大概有以下四个方面:

  • “语法糖”:nullptrauto自动类型推导,范围for循环,初始化列表, lambda表达式等
  • 右值引用和移动语义
  • 智能指针
  • C++11多线程编程:thread库及其相配套的同步原语mutexlock_guardcondition_variable, 以及异步std::furture

1. “语法糖”

c++11新增加了一些语法糖,其中常用的就是auto和lambda。

1.1 auto自动类型推导

C语言也有auto关键字,但是其含义只是与static变量做一个区分,一个变量不指定的话默认就是auto。。因为很少有人去用这个东西,所以在C++11中就把原有的auto功能给废弃掉了,而变成了现在的自动类型推导关键字。用法很简单不多赘述,

比如写一个auto a = 3, 编译器就会自动推导a的类型为int. 在遍历某些STL容器的时候,不用去声明那些迭代器的类型,也不用去使用typedef就能很简洁的实现遍历了。
auto的使用有以下两点必须注意:

  • auto声明的变量必须要初始化,否则编译器不能判断变量的类型。
  • auto不能被声明为返回值,auto不能作为形参,auto不能被修饰为模板参数

关于效率: auto实际上实在编译时对变量进行了类型推导,所以不会对程序的运行效率造成不良影响。另外,auto并不会影响编译速度,因为编译时本来也要右侧推导然后判断与左侧是否匹配。
关于具体的推导规则,可以参考这里

1.2 lambda表达式

lambda表达式是匿名函数,可以认为是一个可执行体functor,语法规则如下:

[捕获区](参数区){代码区};

auto add = [](int a, int b) {return a + b};

就我的理解而言,捕获的意思即为将一些变量展开使得为lambda内部可见,具体方式有如下几种

  • [a,&b] 其中 a 以复制捕获而 b 以引用捕获。
  • [this] 以引用捕获当前对象( *this )
  • [&] 以引用捕获所有用于 lambda 体内的自动变量,并以引用捕获当前对象,若存在
  • [=] 以复制捕获所有用于 lambda 体内的自动变量,并以引用捕获当前对象,若存在
  • [] 不捕获,大部分情况下不捕获就可以了

一般使用场景:sort等自定义比较函数、用thread起简单的线程。

2. 右值引用与移动语义

右值引用是C++11新特性,它实现了转移语义和完美转发,主要目的有两个方面

  • 消除两个对象交互时不必要的对象拷贝,节省运算存储资源,提高效率
  • 能够更简洁明确地定义泛型函数
    C++中的变量要么是左值、要么是右值。通俗的左值定义指的是非临时变量,而左值指的是临时对象。左值引用的符号是一个&,右值引用是两个&&

移动语义
       转移语义可以将资源(堆、系统对象等)从一个对象转移到另一个对象,这样可以减少不必要的临时对象的创建、拷贝及销毁。移动语义与拷贝语义是相对的,可以类比文件的剪切和拷贝。在现有的C++机制中,自定义的类要实现转移语义,需要定义移动构造函数,还可以定义转移赋值操作符。
以string类的移动构造函数为例

MyString(MyString&& str) {std::cout << "Move Ctor source from " << str._data << endl;_len = str._len;_data = str._data;str._len = 0;str._data = NULL;
}

和拷贝构造函数类似,有几点需要注意:

  1. 参数(右值)的符号必须是&&
  2. 参数(右值)不可以是常量,因为我们需要修改右值
  3. 参数(右值)的资源链接和标记必须修改,否则,右值的析构函数就会释放资源。转移到新对象的资源也就无效了。

标准库函数std::move --- 将左值变成一个右值

编译器只对右值引用才能调用移动构造函数,那么如果已知一个命名对象不再被使用,此时仍然想调用它的移动构造函数,也就是把一个左值引用当做右值引用来使用,该怎么做呢?用std::move,这个函数以非常简单的方式将左值引用转换为右值引用。

详情请见:[C++11] 右值引用和移动语义

3.智能指针

核心思想:为防止内存泄露等问题,用一个对象来管理野指针,使得在该对象构造时获得该指针管理权,析构时自动释放(delete).基于此思想C++98提供了第一个智能指针:auto_ptr
   auto_ptr基于所有权转移的语义,即将一个就的auto_ptr赋值给另外一个新的auto_ptr时,旧的那一个就不再拥有该指针的控制权(内部指针被赋值为null),那么这就会带来一些根本性的破绽:

  • 函数参数传递时,会有隐式的赋值,那么原来的auto_ptr自动失去了控制权
  • 自我赋值时,会将自己内部指针赋值为null,造成bug

因为auto_ptr的各种bug,C++11标准基本废弃了这种类型的智能指针,转而带来了三种全新的智能指针:

  • shared_ptr,基于引用计数的智能指针,会统计当前有多少个对象同时拥有该内部指针;当引用计数降为0时,自动释放
  • weak_ptr,基于引用计数的智能指针在面对循环引用的问题将无能为力,因此C++11还引入weak_ptr与之配套使用,weak_ptr只引用,不计数
  • unique_ptr: 遵循独占语义的智能指针,在任何时间点,资源智能唯一地被一个unique_ptr所占有,当其离开作用域时自动析构。资源所有权的转移只能通过std::move()而不能通过赋值

详情请见:[C++11] 智能指针

4、C++11多线程编程

4.1 线程

std::thread

  • 创建std::thread,一般会绑定一个底层的线程。若该thread还绑定好函数对象,则即刻将该函数运行于thread的底层线程。
  • 线程相关的很多默认是move语义,因为在常识中线程复制是很奇怪的行为。
  • joinable():是否可以阻塞至该thread绑定的底层线程运行完毕(倘若该thread没有绑定底层线程等情况,则不可以join)
  • join():本线程阻塞直至该thread的底层线程运行完毕。
  • detach():该thread绑定的底层线程分离出来,任该底层线程继续运行(thread失去对该底层线程的控制)。

4.2 互斥量

为了避免多线程对共享变量的一段操作会发生冲突,引入了互斥体和锁。

std::mutex

  • 互斥体,一般搭配锁使用,也可自己锁住自己(lock(),unlock())。
  • 若互斥体被第二个锁请求锁住,则第二个锁所在线程被阻塞直至第一个锁解锁。

std::lock_guard

  • 简单锁,构造时请求上锁,释放时解锁,性能耗费较低。适用区域的多线程互斥操作。

std::unique_lock

  • 更多功能也更灵活的锁,随时可解锁或重新锁上(减少锁的粒度),性能耗费比前者高一点点。适用灵活的区域的多线程互斥操作。

4.3 原子变量

原子变量的意思就是单个最小的、不可分割的变量(例如一个int),原子操作则指单个极小的操作(例如一个自增操),C++的原子类封装了这种数据对象,使多线程对原子变量的访问不会造成竞争。(可以利用原子类可实现无锁设计)

std::atomic_flag

  • 它是一个原子的布尔类型,可支持两种原子操作。(实际上mutex可用atomic_flag实现)
  • test_and_set(): 如果atomic_flag对象被设置,则返回true; 如果atomic_flag对象未被设置,则设置之,返回false
  • clear():清除atomic_flag对象。

std::atomic<T>

  • 对int, char, bool等基本数据类型进行原子性封装(其实是特化模板)。
  • store():修改被封装的值。
  • load() 读取被封装的值。

4.4 条件变量

条件变量一般是用来实现多个线程的等待队列,即主线程通知(notify)有活干了,则等待队列中的其它线程就会被唤醒,开始干活。

std::condition_variable

  • wait(std::unique_lock<std::mutex>& lock, Predicate pred = [](){return true;}):pred()为true时直接返回,pred()为false时,lock必须满足已被当前线程锁定的前提。执行原子地释放锁定,阻塞当前线程,并将其添加到等待*this的线程列表中。
  • notify_one()/notify_all():激活某个或者所有等待的线程,被激活的线程重新获得锁。

参考:

1、深入理解C++11:C++11新特性解析与应用

2、深入应用C++11:代码优化与工程级应用

3、Effective Modern C++

[C++11] 新特性总结相关推荐

  1. IntelliJ IDEA 使用 Java 11新特性以及Java 8 以来的Java 11新特性介绍

    文章目录 Java 11 安装 IDEA 设置 特性1:lambda表达式中允许使用var 特性2: String新增REPEAT 方法,方便拷贝字符串 特性3: 文件读写更方便:readString ...

  2. Java 11 新特性

    2019独角兽企业重金招聘Python工程师标准>>> Java 11 新特性 转载于:https://my.oschina.net/u/3764794/blog/2993127

  3. C++11新特性中的匿名函数Lambda表达式的汇编实现分析(二)

    2019独角兽企业重金招聘Python工程师标准>>> C++11新特性中的匿名函数Lambda表达式的汇编实现分析(一) 首先,让我们来看看以&方式进行变量捕获,同样没有参 ...

  4. C++11 新特性之std::thread

    C++11 新特性之std::thread 原文:https://blog.csdn.net/oyoung_2012/article/details/78958274 从C++11开始,C++标准库已 ...

  5. C++11新特性之新类型与初始化

    C++11新特性之新类型与初始化 snoone | 2016-06-23 11:57    浏览量(148)    评论(0)   推荐(0) 数据 这是C++11新特性介绍的第一部分,比较简单易懂, ...

  6. Java 11新特性解读

    概述 美国当地时间9月25日,Oracle 官方宣布 Java 11 (18.9 LTS) 正式发布,可在生产环境中使用!这是自 Java 8 后的首个长期支持版本,将支持到2026年,可以使用下面的 ...

  7. C++11新特性decltype

    该博文为原创文章,未经博主同意不得转载,如同意转载请注明博文出处 本文章博客地址:https://cplusplus.blog.csdn.net/article/details/105042574 C ...

  8. 深入浅出之C++11新特性

    1. auto类型赋予新含义 1.1 auto类型定义 在之前的 C++ 版本中,auto 关键字用来指明变量的存储类型,它和 static 关键字是相对的.auto 表示变量是自动存储的,这也是编译 ...

  9. 《深入理解C++11:C++ 11新特性解析与应用》——导读

    前 言 为什么要写这本书 相比其他语言的频繁更新,C++语言标准已经有十多年没有真正更新过了.而上一次标准制定,正是面向对象概念开始盛行的时候.较之基于过程的编程语言,基于面向对象.泛型编程等概念的C ...

  10. C++11 新特性简介

    1.auto auto是旧关键字,在C++11之前,auto用来声明自动变量,表明变量存储在栈,很少使用.在C++11中被赋予了新的含义和作用,用于类型推断. auto关键字主要有两种用途:一是在变量 ...

最新文章

  1. python导入其他py文件-Python如何import其它.py文件及其函数
  2. 如何在spring中读取properties配置文件里面的信息
  3. java 委托_面试官:java双亲委派机制及作用
  4. 根据数据库表gengxin实体类_ASP.NET开发实战——(十二)数据库之EF Migrations
  5. 这难道不是.NET5的bug? 在线求锤?
  6. Django 和 html
  7. LeetCode 2086. 从房屋收集雨水需要的最少水桶数(贪心)
  8. 开发Adobe AIR移动应用程序的考虑事项
  9. Bootstrap框架(基础篇)之列表,表格,表单
  10. Enumerator yielder.yield 与 Proc.yield 区别
  11. JavaScript动态生成表格
  12. 计算机诗人 原理,自动作诗器,藏头诗软件生成器原理是什么?
  13. 中证300、500、800成分股调整时间
  14. html版权登记怎么打,版权符号怎么输入_Html版权符号怎么打
  15. 单片机晶振电路的设计与计算
  16. js的数据类型,深拷贝和浅拷贝的原理,loda实现一个深拷贝
  17. 2018中国大学生程序设计竞赛 – 网络选拔赛 1001 Buy and Resell [模拟]
  18. Unity 4.6.2 iOS 64位支持
  19. stack在python中是什么意思_python中的栈指的是什么
  20. 高性能分布式游戏服务器框架

热门文章

  1. 【李宏毅2020 ML/DL】P75 Generative Adversarial Network | Conditional GAN
  2. ack过来服务器未响应,DHCP服务器问题:抓不到ACK包
  3. java实现 mysql导入_怎么用java实现mysql数据库的导入导出
  4. 中国象棋程序的设计与实现(十)--棋盘的定义和绘制
  5. 使用MATLAB转换图片为数据进行vga显示
  6. html5开发桌面程序调用dll,使用Visual Studio开发Html5应用
  7. User Agent跨站攻击
  8. oracle 01157,Oracle数据库启动时出现ORA-01157和ORA-01110问题
  9. Postgresql Hot_Standby 流复制 基于Linux 对postgresql 和 linux 会基本的操作
  10. 技术博客2013年2月份头条记录