深入理解C++11(一)

导语 从最初的代号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操作符。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏转载gongluck的CSDN博客

cocos2dx 打灰机

#include "GamePlane.h" #include "PlaneSprite.h" #include "BulletNode.h" #include...

7426
来自专栏大内老A

The .NET of Tomorrow

Ed Charbeneau(http://developer.telerik.com/featured/the-net-of-tomorrow/) Exciti...

39510
来自专栏闻道于事

js登录滑动验证,不滑动无法登陆

js的判断这里是根据滑块的位置进行判断,应该是用一个flag判断 <%@ page language="java" contentType="text/html...

8908
来自专栏张善友的专栏

Miguel de Icaza 细说 Mix 07大会上的Silverlight和DLR

Mono之父Miguel de Icaza 详细报道微软Mix 07大会上的Silverlight和DLR ,上面还谈到了Mono and Silverligh...

3017
来自专栏落花落雨不落叶

canvas画简单电路图

89111
来自专栏芋道源码1024

熔断器 Hystrix 源码解析 —— 断路器 HystrixCircuitBreaker

本文主要基于 Hystrix 1.5.X 版本 1. 概述 2. HystrixCircuitBreaker 3. HystrixCircuitBreaker....

5857
来自专栏魂祭心

原 canvas绘制clock

5194
来自专栏一个会写诗的程序员的博客

Spring Reactor 项目核心库Reactor Core

Non-Blocking Reactive Streams Foundation for the JVM both implementing a Reactiv...

2882
来自专栏pangguoming

Spring Boot集成JasperReports生成PDF文档

由于工作需要,要实现后端根据模板动态填充数据生成PDF文档,通过技术选型,使用Ireport5.6来设计模板,结合JasperReports5.6工具库来调用渲...

1.5K7
来自专栏我和未来有约会

Silverlight第三方控件专题

这里我收集整理了目前网上silverlight第三方控件的专题,若果有所遗漏请告知我一下。 名称 简介 截图 telerik 商 RadC...

4435

扫码关注云+社区