前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >深入理解C++11(一)

深入理解C++11(一)

作者头像
MelonTeam
发布2018-01-04 15:22:12
1.1K0
发布2018-01-04 15:22:12
举报
文章被收录于专栏:MelonTeam专栏MelonTeam专栏

导语 从最初的代号C++0x到最终的名称C++11,C++的第二个真正意义上的标准姗姗来迟。

C++11是一种新语言的开端。虽然设计C++11的目的是为了要取代C++98/03,相比于C++03标准,C++11则带来了数量可观的变化,包括了约140个新特性,以及对C++03标准中约600个缺陷的修正。因此,从这个角度看来C++11更像是从C++98/03中孕育出的一种新语言。

从使用上,Scott Mayers为C++11创建了另外一种有效的分类方式,Mayers根据C++11的使用者是类的使用者,还是库的使用者,或者特性是广泛使用的,还是库的增强的来区分各个特性。具体的,可以把特性分为类作者需要的(class writer,简称为”类作者”)、库作者需要的(library writer,简称为”库作者”)、所有人需要的(everyone,简称为”所有人”)、部分人需要的(everyone else,简称为”部分人”)。

1 C++11相对于C++98/03有以下几点的增强:

<1>.通过内存模型、线程、原子操作等来支持本地并行编程(Native Concurrency)。

<2>.通过统一初始化表达式、auto、declytype、移动语义等来统一对泛型编程的支持。

<3>.通过constexpr、POD等更好的支持系统编程。

<4>.通过内联命名空间、继承构造函数和右值引用等,以更好地支持库的构建。

2 保持与C99兼容(类别:部分人)

C语言发展中的大多数改进都被引入了C++语言标准中,但还是存在着一些属于C99标准的”漏网之鱼”。所以C++11将对以下C99特性的支持也都纳入了新标准中:(1)C99中的预定义宏 (2)func__预定义标识符 (3)_Pragma操作符 (4)不定参数宏定义__VA_ARGS (5)宽窄字符串连接

2.1  预定义宏

相较于C89标准,C99语言标准增加一些预定义宏。C++11同样增加了对这些宏的支持,如下表:

宏名称

功能描述

—|—

STDC_HOSTED

如果编译器的目标系统环境中包含完整的标准C库,那么这个宏就定义为1,否则宏的值为0

STDC

C编译器用这个宏的值表示编译器的实现是否和C标准一致。C++11中这个宏是否定义以及定成什么值由编译器决定

STDC_VERSION

C编译器通常用这个宏来表示所支持的C标准的版本。C++11中这个宏是否定义以及定成什么值由编译器决定

STDC_ISO_10646

这个宏定义为一个yyyymml格式的整数常量,例如199712L,用来表示C++编译环境符合某个版本的ISO/IEC 10646标准

2.2  __func__预定义标识符

__func__预定于标识符的基本功能是返回所在函数的名字。

2.3  _Pragma操作符

在C/C++标准中,#pragma是一条预处理的指令。简单的说,#pragma是用来向编译器传达语言标准以外的一些信息。如果在代码的头文件中定义了#pragma once语句,那么该指令会指示编译器,该头文件应该只被编译一次。在C++11中,定义了与预处理指令#pragma功能相同的操作符_Pragma格式如下:

 _Pragma(字符串字面量)

相对于预处理指令#pragma,_Pragma是一个操作符,因此可以用在一些宏中。

2.4 变长参数的宏定义以及__VA_ARGS__

在C99标准中,程序员可以使用变长参数的宏定义,指在宏定义中参数列表的最后一个参数为省略号,__VA_ARGS__可以在宏定义的实现部分替换省略号所代表的字符串。

#define PR(…) printf(VA_ARGS)

2.5  宽窄字符串的连接

在之前的C++标准中,窄字符串(char)转换为宽字符串(wchar_t)是未定义的行为。C++11的标准规定,窄字符串和宽字符串进行连接时,支持C++11标准的编译器将窄字符串转换成宽字符串,然后与宽字符串进行连接。

3.1 扩展的整形(类别:部分人)

C++11中一共只定义了5种标准的有符号整型:(1)signed char (2)short int (3)int (4)long int (5)long long int。同时规定,每一种有符号整型都有一种对应的无符号整数版本,且有符号整型与其对应的无符号整型具有相同的存储空间大小。如与signed int对应的无符号版本的整型是unsigned int。

3.2 静态断言(类别:库作者)

3.2.1 断言:运行时与预处理时

断言(assertion)是编程中常用的手段。一般情况下,断言就是将一个返回值总是需要为真的判别式放在语句中,用于排除在设计的逻辑上不应该产生的情况。在某种意义上,断言并不是正常程序所必需的。不过对于调试程序来说,通常断言能够帮助开发GG快速定位那些违反了某些前提条件的程序错误。在C++中,头文件中提供了assert宏,用于在运行时进行断言。

main函数中对ArrayAlloc的使用没有满足n>0的条件,在运行时,出现Assertion n > 0 failed。

3.2.2 静态断言与static_assert

断言assert宏只有在程序运行时才能起作用。而#error只在编译器预处理是才能起作用。在某些场合,希望能在编译时做一些断言。如下述例子:

本例中,使用了assert断言,assert断言的作用是为了保证a和b两种类型的长度一致,这样bit_copy才能够保证复制操作不会遇到越界等问题。因为assert断言是一个运行时断言,如果出现bit_copy不被调用等情况,我们将无法触发该断言。实际上,为了解决上述问题,正确产生断言的时机应该在模板实例化时,即编译时期的断言,也可以称作为“静态断言”。在实际应用中,我们可以利用“除0”会导致编译器报错这个特性来实现静态断言。

无论是哪种方式的静态断言,缺陷都是非常明显的:诊断信息不够充分,不熟悉该静态断言实现的开发GG可能一时无法将错误对应到断言错误上,从而难以准备定位错误的根源。

在C++11的新标准中,引入了static_assert断言来解决上述问题。static_assert接收两个参数,一个是断言表达式,这个表达式通常需要返回一个bool值,一个是警告信息,通常是一段字符串。使用static_assert替换上述bit_copy的声明。

再次编译上述代码,会出现如下信息:

因为static_assert是编译时期的断言,其使用范围不像assert一样受到限制。在通常情况下,static_assert可以用于任何名字空间。

3.3 noexcept修饰符与noexcept操作符(类别:库作者)

相比较断言排除逻辑上不可能存在的状态,异常用于逻辑上可能发生的错误。在异常处理的代码中,开发GG有可能看到过如下的异常声明表达形式:

void excpt_func() throw(int ,double){……}

在excpt_func()函数声明之后,定义了一个动态异常声明throw(int,double),该声明指出了excpt_func()可能抛出的异常的类型。实际情况下,该特性很少被使用。C++11的新标准中,使用noexcept替换了上述特性。在C++11中,如果noexcept修饰的函数抛出了异常,编译器可以选择直接调用std::terminate()函数终止程序的运行。一般情况下,noexcept修饰符有两种形式:(1)void excpt_func() noexcept; (2)void excpt_func() noexcept(常量表达式);第二种形式中的常量表达式的结果会被转换成一个bool类型的值。若该值为true,表示函数不会抛出异常,反之,则有可能抛出异常。

noexcept作为一个操作符是,通常可以用于模板。

template

void fun() noexcept(noexcept(T())){}

这里,fun函数是否是一个noexcept的函数,将由T()表达式是否抛出异常所决定。这里的第二个noexcept就是一个noexcept操作符。

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2017-07-31,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1 C++11相对于C++98/03有以下几点的增强:
  • 2 保持与C99兼容(类别:部分人)
    • 2.1  预定义宏
      • 2.2  __func__预定义标识符
        • 2.3  _Pragma操作符
          • 2.4 变长参数的宏定义以及__VA_ARGS__
            • 2.5  宽窄字符串的连接
            • 3.1 扩展的整形(类别:部分人)
            • 3.2 静态断言(类别:库作者)
              • 3.2.1 断言:运行时与预处理时
                • 3.2.2 静态断言与static_assert
                • 3.3 noexcept修饰符与noexcept操作符(类别:库作者)
                领券
                问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档