C++11/C++14 新特性学习

1. 类型推导

在标准C++和C,使用参数必须明确的指出其类型。然而,随着模版类型的出现以及模板元编程的技巧,某物的类型,特别是函数定义明确的回返类型,就不容易表示。在这样的情况下,将中间结果存储于参数是件困难的事,可能会需要知道特定的元编程程序库的内部情况。C++11提供如下两种方法缓解上述所遇到的困难。

1.1 auto

能明确根据初始化的参数推导出类型的,可以使用auto关键字。如:

auto对于减少冗赘的代码很有用,如:

1.2 decltype

decltype和auto一起使用会更为有用,因为auto参数的类型只有编译器知道。然而decltype对于那些大量运用运算符重载和特化的类型的代码的表示也非常有用。比typedef更方便、更优雅。

2. 空指针

C++11引入了新的关键字来代表空指针常量:nullptr,将空指针和整数0的概念拆开。 nullptr的类型为nullptr_t,能隐式转换为任何指针或是成员指针的类型,也能和它们进行相等或不等的比较。而nullptr不能隐式转换为整数,也不能和整数做比较。为了向下兼容,0仍可代表空指针常量。

3. 其它关键词

3.1 noexcept

noexcept形如其名,表示其修饰的函数不会抛出异常。

3.2 constexpr

constexpr是常数表达式(constant expression),表示这在编译期就可以算出来。如:

4. 左值和右值

凡是真正的存在内存当中,而不是寄存器当中的值就是左值,其余的都是右值。通俗一点的说法就是:凡是取地址(&)操作可以成功的都是左值,其余都是右值。

5. 引用

对于左值的引用就是左值引用,而对于右值的引用就是右值引用

新准之前我们将左值引用直接称为“引用”。也就是说,我们一直用的int&事实上是对于int类型左值的引用。而对于右值呢?在新标准当中我们使用int&&来表示。通过下例子来体会:

输出:

通用引用(universal reference),传进来的如果是左值引用那就是左值引用,如果是右值引用那就是右值引用。需要注意的是,这个合成规则用户是不允许使用的,只有编译器才能够使用这种合成规则。构成通用引用有两个条件:

  1. 必须满足T&&这种形式
  2. 类型T必须是通过推断得到的

通用引用有如下几种可能:
1. 函数模板参数(function template parameters)

  1. auto声明(auto declaration)

  1. typedef声明(typedef declaration)
  2. decltype声明(decltype declaration)

Scott Meyers建议大家在通用引用的情境下,尽可能使用forward()了,因为这样可以在不改变语义的情况下提升性能。

6. 初始化

6.1 初始化列表

直接看例子就明白了。

6.2 统一初始化

统一初始化不会取代构造函数语法。仍然会有需要用到构造函数语法的时候。如果一个类别拥有初始化列表构造函数(TypeName(initializer_list);),而初始化列表与构造函数的参数类型一致,那么它比其他形式的构造函数的优先权都来的高。

像std::vector将会有初始化列表构造函数。要使用这个构造函数,用户必须直接使用标准的构造函数语法。参考如下例子:

7. 基于范围的for循环

很多开发语言都有的特性,直接看例子就明白了。

8. 智能指针

这些指针是由TR1智能指针演变而来。注意! 智能指针是类别而非一般指针。

shared_ptr是一引用计数(reference-counted)指针,其行为与一般C++指针极为相似。在TR1的实现中,缺少了一些一般指针所拥有的特色,像是别名或是指针运算。

shared_ptr只有在已经没有任何其它shared_ptr指向其原本所指向对象时,才会销毁该对象。

weak_ptr指向的是一个被shared_ptr所指向的对象。该weak_ptr可以用来决定该对象是否已被销毁。weak_ptr不能被解引用;想要访问其内部所保存的指针,只能通过shared_ptr。有两种方法可达成此目的。第一,类别shared_ptr有一个以weak_ptr为参数的构造函数。第二,类别weak_ptr有一个名为lock的成员函数,其回返值为一个shared_ptr。weak_ptr并不拥有它所指向的对象,因此不影响该对象的销毁与否。

auto_ptr将会被C++标准所废弃,取而代之的是unique_ptr。unique_ptr提供auto_ptr大部分特性,唯一的例外是auto_ptr的不安全、隐性的左值搬移。不像auto_ptr,unique_ptr可以存放在C++11提出的那些能察觉搬移动作的容器之中。

另外可参考http://www.cnblogs.com/TenosDoIt/p/3456704.html

9. 线程库

10. 原子操作

11. 内存模型

多核
顺序一致性模型

12. 移动语义和完美转发

掌握这些需要对左值(引用)、右值(引用)很清楚。

std::move, std::forward

13. 变长参数的模板

14. 仿函数

std::function 仿函数,std::bind 函数绑定

15. Lambda表达式

16. 委托构造

defaulted 和deleted 函数

17. 新的算法

all_of(), any_of() , none_of()

18. array

参考

  1. https://zh.wikipedia.org/wiki/C%2B%2B11(打不开,都懂的)
  2. http://en.cppreference.com/w/cpp
  3. https://codinfox.github.io/dev/2014/06/03/move-semantic-perfect-forward/ ,这篇文章对左值、右值、左值引用、右值引用、 移动语义、完美转发解释得特别清楚。