牛骨文教育服务平台(让学习变的简单)
博文笔记

C++11新版本

创建时间:2015-11-02 投稿人: 浏览次数:504

   C++11标准发布已有一段时间了, 维基百科上有对C++11新标准的变化和C++11新特性介绍的文章。

以下是关于C++11的英文版本和中文版本维基百科的链接:

http://en.wikipedia.org/wiki/C++11

http://zh.wikipedia.org/wiki/C++0x

   目录

   0.简介

C++11,之前被称作C++0x,即ISO/IEC 14882:2011,是目前的C++编程语言的正式标准。它取代第二版标准ISO/IEC 14882:2003(第一版ISO/IEC 14882:1998发布于1998年,第二版于2003年发布,分别通称C++98以及C++03,两者差异很小)。新的标准包含了几个核心语言增加的新特性,而且扩展C++标准程序库,并入了大部分的C++ Technical Report 1程序库(数学的特殊函数除外)。最新的消息被公布在 ISO C++ 委员会网站(英文)。

ISO/IEC JTC1/SC22/WG21 C++ 标准委员会计划在2010年8月之前完成对最终委员会草案的投票,以及于2011年3月召开的标准会议完成国际标准的最终草案。然而,WG21预期ISO将要花费六个月到一年的时间才能正式发布新的C++标准。为了能够如期完成,委员会决定致力于直至2006年为止的提案,忽略新的提案。最终,于2011年8月12日公布,并于2011年9月出版。2012年2月28日的国际标准草案(N3376)是最接近于现行标准的草案,差异仅有编辑上的修正。

像C++这样的编程语言,通过一种演化的过程来发展其定义。这个过程不可避免地将引发与现有代码的兼容问题。不过根据Bjarne Stroustrup(C++的创始人,标准委员会的一员)表示,新的标准将几乎100%兼容现有标准。

 

1.来自以往版本标准的变更(候选变更)

C++的修订范围包括核心语言以及标准程序库。在开发2011版标准的各个特性的过程中,标准委员会坚持以下指导思想:
    * 维持与C++98,可能的话还有C之间的兼容性稳定性
    * 尽可能通过通过标准程序库来引进新的特性, 而不是扩展核心语言;
    * 能够促进编程技术的变更优先;
    * 改进 C++ 以帮助系统和程序库的设计,而不是引进只对特定应用有用的新特性;
    * 增强类型安全,给现行不安全的技术提供更安全的替代方案;
    * 增强直接与硬件协同工作的性能和能力;
    * 为现实世界中的问题提供适当的解决方案;
    * 实行零负担原则(如果某些功能要求的额外支持,那么只有在该功能被用到时这些额外的支持才被用到);
    * 使C++易于教学

注重对初学者的关注,因为他们构成了计算机程序员的主体。也因为许多初学者不愿扩展他们的C++知识,他们仅限于掌握C++中自己所专精的部分. 

 

2.核心语言的扩充

C++标准委员会的一个职责是开发语言核心. 核心语言被大幅改进的领域包括: 多线程支持, 泛型编程支持, 统一的初始化和提高性能.
    这篇文章将核心语言的特性和变化大致分为: 提高运行期性能, 提高编译期性能, 增强可用性, 和新特性4大类. 某些特性可以被划分到多个分类中, 但只会在主要体现该特性的分类中讨论一次.

 

3.提高核心语言运行性能
    以下特性主要是为了提高性能提或计算速度等设计的.

3.1 右值引用和移动构造
    在C++03及之前的标准中,临时对象(称为右值"R-values",因为通常位于赋值运算符的右边)的值是不能改变的,和C语言一样, 且无法和 const T& 类型做出区分。尽管在某些情况下临时对象的确会被改变,甚至有时还被视为是一个有用的漏洞。C++11新增加了一个非常量引用(non-const reference)类型,称作右值引用(R-value reference),标记为T &&。右值引用所引用的临时对象可以在该临时对象被初始化之后做修改,这是为了允许 move 语义。
    C++03 性能上被长期诟病的问题之一,就是其耗时且不必要的深拷贝。深拷贝会隐式地发生在以传值的方式传递对象的时候。例如,std::vector内部封装了一个C风格的数组和其元素个数,如果创建或是从函数返回一个std::vector的临时对象,要将其保存起来只能通过生成新的std::vector对象并且把该临时对象所有的数据复制进去。该临时对象和其拥有的內存会被销毁。(为简单起见,这里忽略了编译器的返回值优化)
    在 C++11中,std::vector有一个"移动构造函数",对某个vector的右值引用可以单纯地从右值复制其内部C风格数组的指针到新的vector中,然后将右值中的指针置空。因为这个临时对象不会再被使用,没代码会再访问这个空指针, 而且因为这个临时对象的内部指针是NULL,所以当这个临时对象离开作用域时它的内存也不会被释放掉.所以,这个操作不仅没有代价高昂的深拷贝, 还是安全的,对用户不可见的!

这个操作不需要数组的复制,而且空的临时对象的析构也不会销毁内存。返回vector临时对象的函数只需要返回std::vector<T>&&。如果vector没有move 构造函数,那么就会调用常规拷贝构造函数。如果有,那么就会优先调用move构造函数,这能够避免大量的内存分配和内存拷贝操作。

右值引用不用对标准库之外的代码做任何改动就可以为已有代码带来性能上的提升. 返回值类型为std::vector<T>的函数返回了一个std::vector<T>类型的临时对象,为了使用移动构造不需要显示地将返回值类型改为std::vector<T>&&, 因为这样的临时对象会被自动当作右值引用. 但是在c++03中, std::vector<T>没有移动构造函数, 带有const std::vector<T>& 参数的拷贝构造会被调用, 这会导致大量内存分配和拷贝动作.
出于安全考虑, 需要施加一些限制! 一个已命名的变量即使声明为右值,也不会被视为右值.想要获取一个右值,应该使用模板函数std::move<T>(). 右值引用也可以在特定情况下被修改, 主要是为了与移动构造函数一起使用!
由于"右值引用"这个词的自然语义,以及对"左值引用"(常规引用)这个词的修正, 右值引用可以让开发者提供完美的函数转发! 与可变参数模板结合时, 这个能力让模板函数能够完美地将参数转发给带有这些参数的另一个函数.这对构造函数的参数转发最为有用,创建一个能够根据特定的参数自动调用适当的构造函数的工厂函数.

3.2 泛化的常数表达式

  C++一直以来都有常量表达式的概念.这种表达式就像3+4这种在编译期和运行时都能得到相同结果的表达式. 常量表达式给编译器提供了优化的机会, 编译器计算出他们的值并把结果硬编码到程序中. 并且C++规格文档中有很多地方要求使用常量表达式. 例如,定义一个数组需要常量表达式(来指定数组大小), 枚举值必须是常量表达式.
      然而,常量表达式中从来都不允许调用函数或创建对象. 所以,像下面这样的简单代码却是非法的:

int get_five() {return 5;} 
int some_value[get_five() + 7]; // 创建一个包含12个整数的数组. 这种形式在C++中是非法的.
声明:该文观点仅代表作者本人,牛骨文系教育信息发布平台,牛骨文仅提供信息存储空间服务。