C++11特性-概览

2019-05-26  本文已影响0人  WalkeR_ZG

C++11(也称C++2.0、Modern C++) 是继C++98(C++1.0) 之后的第二个国际标准规格,其对C++的改变是全方位的,有人也说C++11是一门新的语言。C++11增加了非常多的新特性,而这些新特性对于开发效率的提升非常明显。

C++11支持的编程范式:

关于C++11支持的编程范式初步考虑会写一篇博客进行介绍,而其中的函数式编程是以前C++版本所不具备的,并且C++11对泛型编程及元编程都有所改进。

C++11的新关键字

template<typename It>
void dwim(It b, It e)
{
   while(b != e){
       typename std::iterator_traits<It>::value_type currValue = *b;
       ...
    }
}
template<typename It>
void dwim(It b, It e)
{
    while(b != e){
       auto currValue = *b;
       ...
    }
}
存储期 implication
自动 automatic 对象的存储在外围代码块开始时分配,而在结束时解分配。未声明为 staticexternthread_local 的所有局部对象均拥有此存储期。
静态 static 对象的存储在程序开始时分配,而在程序结束时解分配。只存在对象的一个实例。所有声明于命名空间作用域(包含全局命名空间)的对象,加上声明带有 staticextern 的对象均拥有此存储期。
动态 dynamic 对象的存储通过使用动态内存分配函数来按请求进行分配和释放的。
线程 thread 对象的存储在线程开始时分配,而在线程结束时释放。每个线程拥有其自身的对象实例。唯有声明为 thread_local 的对象拥有此存储期。

thread_local可以用于修饰三种变量:全局变量、类的static成员变量及本地变量,此时变量即拥有线程生命周期及线程可见性的变量。

C++11的重要新特性

笔者认为对C++有重要变革的新特性有:多线程编程、lambda表达式、可变参数模板、正则表达式、智能指针及右值引用。

多线程编程

C++11前没有提供对多进程并发的原生支持,所以C++的多进程并发要依赖平台相关的API实现。C++11 标准的推出在语言层面对多线程编程提供了原生支持,极大的提高了程序的可移植性。
C++11 新标准中引入了几个头文件来支持多线程编程:
< thread > :包含std::thread类以及std::this_thread命名空间。主要负责运行及管理线程。
< atomic > :包含std::atomic和std::atomic_flag类,定义了一些原子操作。
< mutex > :包含了与互斥量相关的类以及其他类型和函数用于线程同步。互斥避免多个线程同时访问共享资源。这会避免数据竞争,并提供线程间的同步支持。
< future > :包含两个Provider类(std::promise和std::package_task)和两个Future类(std::future和std::shared_future),promise和future用于在线程间传递异步结果,packaged_task来封装可以产生这种异步结果的函数调用.。
< condition_variable > :包含与条件变量相关的类,包括std::condition_variable和std::condition_variable_any。条件变量是允许多个线程相互交流的同步原语。它允许一定量的线程等待(可以定时)另一线程的唤醒,然后再继续。条件变量始终关联到一个互斥。

多线程编程后续会在博客中专门阐述。

lambda表达式

Lambda表达式在C++11中引入,利用Lambda表达式,可以方便的定义和创建匿名函数。lambda表达式在其他语言中都有提供,lambda表达式的引入也使得C++可以用于函数式编程范式。lambda表达式的形式如下:

[capture list] (params list) mutable exception-> return type { function body }
name implication
capture list 捕获外部变量列表,可以值捕获、引用捕获,也可以混合捕获
params list 形参列表
mutable指示符 表明函数体内的代码可以修改值捕获的变量
exception 异常设定
return type 返回类型
function body 函数体
可变参数模板

C++11之前类模版和函数模版中只能含固定数量的模版参数,可变模版参数(variadic templates)对参数进行了高度泛化,它能表示0到任意个数、任意类型的参数。

template <class... T>
void f(T... args);

可变参数模板的定义一般都会使用模版偏特化和递归方式两种技巧。C++11引入的元组tuple就是一种可变参数模板的应用。

正则表达式

C++11提供了正则表达式库,正则表达式是一种用于在字符串中匹配模式的微型语言。提供主要3种算法,regex_match确定正则表达式是否匹配整个目标字符序列;regex_search 确定正则表达式和目标字符序列中的某个子序列间是否有匹配;regex_replace以格式化的替换文本来替换正则表达式匹配的出现位置 。

name implication
目标序列 可以是二个迭代器所指定的范围、空终止字符串或一个 std::string 。
模式 正则表达式自身。它确定构成匹配者。它是从带特定语法的字符串构成的 std::basic_regex 类型对象。受支持的语法变体的描述见 syntax_option_type 。
匹配的数组 关于匹配的信息可作为 std::match_results 类型对象获取。
替换字符串 确定如何替换匹配的字符串,受支持的语法变体的描述见 match_flag_type 。
智能指针

C++从业者在使用指针时,都会遇到的两类问题,一是悬空指针,二是内存泄漏。这些都是在使用指针时经常遇到的问题,而C++11引入的智能指针能很好的应对以上问题,让C++从业者对内存管理不再谈虎色变。

name implication
unique_ptr 独占指针对象,并保证指针所指对象生命周期与其一致。<所有权唯一>
shared_ptr 可共享指针对象,可以赋值给shared_ptr或weak_ptr。所有关联的shared_ptr生命周期结束时对象生命周期结束。<共享所有权>
weak_ptr 它不能决定所指对象的生命周期,引用所指对象时,需要lock()成shared_ptr才能使用。<为了解决shared_ptr循环引用问题引入>
右值引用

右值引用是C++11中引入的,它是为了提高运行效率避免一些无意义的深拷贝而引入的。C++中所有的值都必然属于左值、右值二者之一。关于左值和右值的最初的定义是,左值既可以出现在赋值符号的左侧,也可以出现在赋值符号的右侧的值,右值是只能出现在赋值符号右侧的值。而目前区分左值和右值的一个方法就是看能对不能对其进行取地址,如果能则为左值,如果不能则为右值。对于右值引用,其与move和完美转发联系非常紧密,move与RVO、universal reference后面会专门写博客对其阐述。

C++11的其他增强

初始化列表initializer_list

初始化列表{}的引入使得变量的初始化更加优雅,特别对于STL容器,C++11可以和其他类型一样进行初始化,另外在前面的博客<The Most Vexing Parse In C++>中,可以看到使用初始化列表方式可以消除C++中很多令人困惑的解析。

基于范围的for循环

在C++11之前对于容器类的遍历会写一大坨代码,而C++11新入的auto和基于范围的for循环,可以很优雅的对容器元素进行遍历。

强类型枚举

在C++11之前枚举不是类型安全的,它实际是整数,并且具体使用哪种整数类型是由编译器定义的,此外枚举值是暴露在外层作用域的,所以即便是两种不同的枚举类型也不能使用相同的名字。C++11引入的enum class是类型安全的,不会隐式转化为整数,并且其作用域是枚举类内部。

C++11其他的小特性在关键字章节有所提及,后续会对几个重要的特性专门阐述。

WalkeR_ZG

上一篇 下一篇

猜你喜欢

热点阅读