C++ 11 新特性梳理

论坛 期权论坛 期权     
CPP开发者   2019-6-9 21:25   4044   0
(给CPP开发者加星标,提示C/C++技能)

来源:杭河苇
https://www.jianshu.com/p/78c700c8d72d
在面试中,经常被问的一个问题就是:你了解C++11哪些新特性?一般而言,回答以下四个方面就够了:

  • “语法糖”:nullptr, auto自动类型推导,范围for循环,初始化列表, lambda表达式等
  • 右值引用和移动语义
  • 智能指针
  • C++11多线程编程:thread库及其相配套的同步原语mutex, lock_guard, condition_variable, 以及异步std::furture
[h2][/h2][h2]1、“语法糖”[/h2]
这部分内容一般是一句话带过的,但是有时候也需要说一些,比较重重要的就是auto和lambda。


[h2]auto自动类型推导[/h2]
C语言也有auto关键字,但是其含义只是与static变量做一个区分,一个变量不指定的话默认就是auto。。因为很少有人去用这个东西,所以在C++11中就把原有的auto功能给废弃掉了,而变成了现在的自动类型推导关键字。用法很简单不多赘述,比如写一个auto a = 3, 编译器就会自动推导a的类型为int. 在遍历某些STL容器的时候,不用去声明那些迭代器的类型,也不用去使用typedef就能很简洁的实现遍历了。

auto的使用有以下两点必须注意:

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

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

关于具体的推导规则,可以参考这里http://www.cnblogs.com/boydfd/p/4950334.html

[h2]lambda表达式[/h2]
lambda表达式是匿名函数,可以认为是一个可执行体functor,语法规则如下:
  1. [捕获区](参数区){代码区};
复制代码
  1. auto add = [](int a, int b) {return a + b};
复制代码
就我的理解而言,捕获的意思即为将一些变量展开使得为lambda内部可见,具体方式有如下几种

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

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

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

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

移动语义

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

以string类的移动构造函数为例
  1. MyString(MyString&& str) {
  2.     std::cout cnt;
  3.         if(ptr_counter.cnt == 0)
  4.             delete ptr_counter;
  5.     }
  6. private:
  7.     Counter *ptr_counter;
  8. };
复制代码
需要记住的事,在以下三种情况下会引起引用计数的变更:

1、调用构造函数时: SmartPointer p(new Object());
2、赋值构造函数时: SmartPointer p(const SmartPointer &p);
3、赋值时:SmartPointer p1(new Object()); SmartPointer p2 = p1;
[h2][/h2][h2]C++11多线程编程[/h2]
[h2]线程 #include [/h2]
std::thread可以和普通函数和lambda表达式搭配使用。它还允许向线程执行函数传递任意多参数。
  1. #include
  2. void func() {
  3. // do some work here
  4. }
  5. int main() {
  6.    std::thread thr(func);
  7.    t.join();
  8.    return 0;
  9. }
复制代码

上面就是一个最简单的使用std::thread的例子,函数func()在新起的线程中执行。调用join()函数是为了阻塞主线程,直到这个新起的线程执行完毕。线程函数的返回值都会被忽略,但线程函数可以接受任意数目的输入参数。

[h2]std::thread的其他成员函数[/h2]
  • joinable(): 判断线程对象是否可以join,当线程对象被析构的时候如果对象``joinable()==true会导致std::terminate`被调用。
  • join(): 阻塞当前进程(通常是主线程),等待创建的新线程执行完毕被操作系统回收。
  • detach(): 将线程分离,从此线程对象受操作系统管辖。
[h2][/h2][h2][/h2][h2]线程管理函数[/h2]
除了std::thread的成员函数外,在std::this_thread命名空间也定义了一系列函数用于管理当前线程。

函数名作用get_id返回当前线程的idyield告知调度器运行其他线程,可用于当前处于繁忙的等待状态。相当于主动让出剩下的执行时间,具体的调度算法取决于实现sleep_for指定的一段时间内停止当前线程的执行sleep_until停止当前线程的执行直到指定的时间点
至于mutex, condition_variable等同步原语以及future关键字的使用这里不做详细介绍,如果用过自然可以说出,没有用过的话这部分内容也不应该和面试官讨论。

推荐阅读
(点击标题可跳转阅读)
C++17 中那些值得关注的特性
C++ 指针详解
如何编写 C++ 游戏引擎


看完本文有帮助?请分享给更多人
关注「CPP开发者」加星标,提升C/C++技能

分享到 :
0 人收藏
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

积分:110
帖子:22
精华:0
期权论坛 期权论坛
发布
内容

下载期权论坛手机APP