VS2010、VS2012、VS2013对C++11的支持进度

原帖地址: http://msdn.microsoft.com/zh-cn/library/hh567368.aspx


对 C++11 功能的支持(现代 C++)

Visual Studio 2013
其他版本
3(共 6)对本文的评价是有帮助 评价此主题

本文档描述了在 Visual C++ 中实现的 C++11 功能。 此信息是根据 Stephan T 发布的 Visual C++ 团队博客进行改编的。 Lavavej.

本节内容
  • C++11 功能列表

    • 核心语言功能表

    • 核心语言功能表:并发

    • 核心语言功能表:C99

  • 功能表指南

    • 右值引用

    • Lambdas

    • decltype

    • 强类型/前向声明枚举

    • 对齐

    • 标准布局和普通类型

    • 默认函数和已删除的函数

    • override 和 final

    • 原子化及更多信息

  • 标准库功能

C++11 功能列表

Visual Studio 2010 中的 Visual C++ 实现了 C++11 核心语言规范中的多种功能,并且 Visual Studio 2012 中的 Visual C++ 添加了更多 C++11 功能。 Visual Studio 2013 中的 Visual C++ 进一步扩展了此覆盖范围,并且还支持一些精选的 C++14 库功能。 下表列出了 C++11 核心语言功能及其在 Visual Studio 2010、Visual Studio 2012 中的 Visual C++ 和 Visual Studio 2013 中的 Visual C++ 中的 Visual C++ 中的实现状态。

C++11 核心语言功能表

C++11 核心语言功能

Visual Studio 2010

Visual Studio 2012

Visual Studio 2013

右值引用 0.1 版、1.0 版、2.0 版、2.1 版、3.0 版

2.0 版

2.1* 版

2.1* 版

引用限定符

非静态数据成员初始值设定项

可变参数模板 0.9 版、1.0 版

初始值设定项列表

static_assert

auto 0.9 版、1.0 版

1.0 版

v1.0

1.0 版

尾部的返回类型

Lambdas 0.9 版、1.0 版、1.1 版

1.0 版

1.1 版

1.1 版

decltype 1.0 版、1.1 版

v1.0

1.1** 版

1.1 版

右尖括号

函数模板的默认模板参数

表达式 SFINAE

别名模板

Extern 模板

nullptr

强类型的枚举

Partial

前向声明枚举

特性

constexpr

对齐

TR1

Partial

Partial

委托构造函数

继承构造函数

显式转换运算符

char16_t/char32_t

Unicode 字符串文本

原始字符串文本

文本中的通用字符名

用户定义的文本

标准布局和普通类型

默认函数和已删除的函数

是*

扩展的友元声明

扩展的 sizeof

内联命名空间

无限制的联合

作为模板参数的本地和未命名类型

基于范围的 for 循环

override 和 final 0.8 版、0.9 版、1.0 版

Partial

最低 GC 支持

noexcept

[转到页首]

C++11 核心语言功能表:并发

C++11 核心语言功能:并发

Visual Studio 2010

Visual Studio 2012

Visual Studio 2013

改写的序列点

不可用

不可用

不可用

原子化

强比较和交换

双向界定

内存模型

不可用

不可用

不可用

数据依赖项排序

数据依赖项排序:函数批注

exception_ptr

quick_exit

信号处理程序中的原子化

线程本地存储

Partial

Partial

Partial

神奇的静态对象

[转到页首]

C++11 核心语言功能:C99

C++11 核心语言功能:C99

Visual Studio 2010

Visual Studio 2012

Visual Studio 2013

__func__

Partial

Partial

Partial

C99 预处理器

Partial

Partial

Partial

long long

扩展的整型

不可用

不可用

不可用

[转到页首]

功能表指南

右值引用

说明

以下描述中使用的版本标识符(0.1 版、1.0 版、2.0 版、2.1 版、3.0 版)仅用来演示 C++11 的发展。 标准本身不会使用它们。

N1610“通过右值澄清类对象的初始化”是早期在不引用右值的情况下支持移动语义的一种尝试。为方便讨论,我们称之为“右值引用 0.1 版”。 它由“右值引用 1.0 版”取代。“右值引用 2.0 版”是 Visual Studio 2010 中的 Visual C++ 功能的基础,它禁止将右值引用绑定到左值,因此可以解决主要的安全性问题。“右值引用 2.1 版”重新定义了此规则。让我们看一下 vector::push_back(),它具有重载 push_back(const string&) 和 push_back(string&&) 以及调用 v.push_back("strval")。表达式 "strval" 是字符串,并且是左值。(其他文本为右值,如整数 1729,但字符串有些特殊,因为它们是数组。)“右值引用 2.0 版”规则显示,string&& 无法绑定到 "strval",因为 "strval" 是左值,因此 push_back(const string&) 是唯一可行的重载。这将创建一个临时 std::string,并将它复制到向量中,然后销毁效率不太高的临时 std::string “右值引用 2.1 版”规则确认,将 string&& 绑定到 "strval" 将创建临时 std::string,并且该临时字符串为右值。因此,push_back(const string&) 和 push_back(string&&) 都是可行的,但首选 push_back(string&&)。将构造一个临时 std::string,然后将它移至向量中。这样效率更高。

“右值引用 3.0 版”将添加新规则,以在特定条件下自动生成移动构造函数和移动赋值运算符。 但由于时间和资源限制,这未在 Visual Studio 2013 中的 Visual C++ 中实现。

[转到页首]

Lambdas

在 lambda 函数选入到工作文件(“0.9”版)并且已添加可变的 lambda(“1.0”版)之后,标准化委员会全面修订了措词。 这产生了 lambda“1.1”版,这个版本现在已完全受支持。lambda 1.1 版的措词阐明了在特殊案例(例如引用静态成员或嵌套 lambda)中会发生的情况。这将修复由复杂 lambda 触发的问题。此外,无状态的 lambda 现在可转换为函数指针。这没有包含在 N2927 措词中,但是无论如何都会将它计作 lambda 1.1 版的一部分。C++115.1.2 [expr.prim.lambda]/6 具有以下说明:“无 lambda-capture 的 lambda-expression 的闭包类型使用一个公共的非虚拟、非显式常量转换函数指向一个具有与闭包类型的函数调用运算符相同的参数和返回类型的函数。 此转换函数返回的值应为一个函数的地址,调用该函数时,其效果和调用闭包类型的函数调用运算符相同。”(Visual Studio 2012 中的 Visual C++ 实现的效果甚至更好,因为它使无状态的 lambda 可转换为具有任意调用约定的函数指针。当你在使用期待像 __stdcall 函数指针这类对象的 API 时,这点很重要。)

[转到页首]

decltype

在 decltype 选入到工作文件(1.0 版)后,在最后时刻收到了一个小的但很重要的修复(1.1 版)。这对从事 STL 和 Boost 工作的程序员很有好处。

[转到页首]

强类型/前向声明枚举

Visual Studio 2010 中的 Visual C++ 部分支持强类型的枚举(具体而言是,有关显式指定的基础类型的部分)。 现在这些在 Visual Studio 中已完全实现,前向声明枚举的 C++11 语义也已完全实现。

[转到页首]

对齐

选入工作文件的对齐方式提案中的核心语言关键字 alignas/alignof 未实现。Visual Studio 2010 中的 Visual C++ 具有来自 TR1 的 aligned_storage。 Visual Studio 2012 中的 Visual C++ 已将 aligned_union 和 std::align() 添加到标准库,而且重大的问题已在 Visual Studio 2013 中的 Visual C++ 中修复。

[转到页首]

标准布局和普通类型

来自 N2342“POD 重新访问;解决核心问题 568(修订 5)”的公开更改是将 is_trivial 和 is_standard_layout 添加到标准模板库的 。(N2342 修改了大量核心语言措词,但无需进行编译器更改。)这些类型特征在 Visual Studio 2010 的 Visual C++ 中已提供,但它们只是复制了 is_pod。 因此,本文档中之前的表显示“不支持”。它们现在由设计用于给出精确答案的编译器挂钩驱动。

STL 的 common_type<> 在 Visual Studio 2013 中的 Visual C++ 中得到了迫切需要的修复。common_type<>的 C++11 规范导致意外后果;具体而言,它使 common_type::type 返回 int&&。 因此,Visual Studio 2013 中的 Visual C++ 可实现建议用于库工作组问题 2141 的解决方法,使 common_type::type 返回 int

作为此更改的副作用,标识用例不再起作用(common_type 并不总是产生 T 类型)。 这将遵循建议的解决方法,但其将中断依赖于先前行为的所有代码。

如果需要标识类型特征,请不要使用  中定义的非标准 std::identity,因为它对  无效。 相反,实现您自己的标识类型特征以满足您的需求。 以下是一个示例:

C++
template <typename T> struct Identity {
    typedef T type;
};

说明

有关其他重大更改,请参见 Visual C++ 中的重大更改

[转到页首]

默认函数和已删除的函数

这些函数现在均受支持,但此种情况例外:对于默认函数,不支持使用 =default 请求识别成员的移动构造函数和移动赋值运算符。 复制和移动操作并不按照标准规定的方式进行精确交互 - 例如,指定删除移动会同时禁止显示复制操作,但 Visual Studio 2013 中的 Visual C++ 不会。

有关如何使用默认函数和已删除的函数的信息,请参见 C++ 函数定义

[转到页首]

override 和 final

这经历了短暂而复杂的发展。 最初,在 0.8 版中,具有 [[override]]、[[hiding]] 和 [[base_check]] 特性。然后在 0.9 版中,消除了这些特性并将其替换为上下文关键字。最后,在 1.0 版中,将它们精简为类的“final”以及函数的“override”和“final”。这使它成为一个获得提升的扩展,因为 Visual Studio 2010 中的 Visual C++ 已支持对函数使用此“override”语法,并且语义相当接近于 C++11 中的语义。“final”也受支持,但拼写不同(“sealed”)。现在完全支持“override”和“final”的标准拼写和语义。 有关更多信息,请参见override 说明符final 说明符

[转到页首]

原子化及更多信息

原子化、强比较和交换、双向界定和数据依赖项排序指定现在已实现的标准库机制。

相关 STL 标头:  和 

[转到页首]

标准库功能

这涵盖核心语言。 至于 C++11 标准库,我们虽没有漂亮的功能比较表,但 Visual Studio 2012 中的 Visual C++ 已实现此功能,但具有两个例外。首先,当某个库功能依赖于编译器中缺少的功能时,该功能要么是模拟的(例如,make_shared() 的模拟可变参数模板),要么没有实现。(仅有少数情况现在已经在 Visual Studio 2013 中的 Visual C++ 中完全实现,其中最值得注意的是 。)C99 已在 Visual Studio 2013 中的 Visual C++ 和提供的 C++ 包装器标头中实现,并且例外情况非常少。 有关更多信息,请参阅 Visual Studio 2013 中的 C99 库支持。

下面列出了 Visual Studio 2012 中的 Visual C++ 和 Visual Studio 2013 中的 Visual C++ 中的部分更改:

定位:根据 C++11 的要求,emplace()/emplace_front()/emplace_back()/emplace_hint()/emplace_after() 已在所有包含“任意”数量参数的容器中实现(请参见“模拟的可变参数”部分)。例如,vector 具有“template void emplace_back(Args&&... args)”(它在向量的后面从任意数量的任意参数时直接构造元素类型 T,这称为“完全转发”)。这相对于 push_back(T&&)(将涉及额外的移动构造和析构)效率更高。

可变参数:Visual Studio 2012 中的 Visual C++ 具有用于模拟可变参数模板的方案。 在 Visual Studio 2013 中的 Visual C++ 中,取消了模拟,并完全实现了可变参数 如果你的代码依赖旧的模拟可变参数行为,则必须修复它。 但是,切换到实际可变参数模板增加了编译次数,并降低了编译器的内存消耗

显式转换运算符:在核心语言中,显式转换运算符是一项常规功能 — 例如,你可以具有 explicit operator MyClass()。 但是,标准库当前仅使用一种形式:explicit operator bool(),这使类成为安全的布尔值可测试的类。(无格式“operator bool()”是非常危险的。)过去,Visual C++ 模拟了带有 operator pointer-to-member() 的 explicit operator bool(),这导致各种问题,并且效率有些低下。 现在,完全移除了此“虚拟 bool”工作区。

随机性: uniform_int_distribution 现在是完全公平的,并且在  中实现了 shuffle(),这样便可以直接接受统一随机数生成器,如 mersenne_twister

防止重载 address-of 运算符:C++98/03 禁止 STL 容器的元素重载其 address-of 运算符。这是类似 CComPtr 的类完成的操作,因此使 STL 避免此类重载需要类似 CAdapt 的帮助程序类。开发 Visual Studio 2010 中的 Visual C++ 时,STL 更改使其在更多情况下拒绝重载 address-of 运算符。 C++11 更改了相关要求,使得重载 address-of 运算符可接受。 Visual Studio 2010 中的 C++11 和 Visual C++ 提供帮助程序函数 std::addressof(),此函数可获取对象的真实地址(无论运算符是否重载)。在发布 Visual Studio 2010 中的 Visual C++ 之前,我们已尝试将“&elem”替换为具有一定抵抗性的“std::addressof(elem)”。Visual Studio 2012 中的 Visual C++ 更进一步,这样重载 address-of 运算符的类就能在整个 STL 中使用了。

Visual Studio 2012 中的 Visual C++ 在下列方面超出了 C++11 的范围:

SCARY 迭代器:实现了 SCARY 迭代器,如 N2911“在泛型类中最小化依赖项以获得更快且更小的程序”和 N2980“SCARY 迭代器分配和安装,第一版”中所述,这在 C++11 标准是允许的,但不是必需的。

文件系统:已添加 TR2 建议中的  标头。 它提供 recursive_directory_iterator 和其他有趣功能。在 TR2 的工作冻结之前,由于 C++0x 很晚才投入运行且将更改为 C++11,因此从 Boost.Filesystem V2 派生出了 2006 协议。 它稍后将演变为 Boost.Filesystem V3,但未在 Visual Studio 2012 中的 Visual C++ 中实现。

一个主要优化!现在,我们的所有容器相对于当前的表示形式都具有最小的合适大小。这指的是容器对象本身,而不是它们指向的内容。例如,std::vector 包含三个原始指针。在 Visual Studio 2010 中的 Visual C++ 中,x86 发布模式std::vector 为 16 字节。在 Visual Studio 2012 中的 Visual C++ 中,它为 12 字节,这是最小的合适大小。如果你的程序有 100,000 个向量,则 Visual Studio 2012 中的 Visual C++ 将为你节省 400,000 字节,这很了不起。减少内存使用率可节省空间和时间。

这是通过避免存储空的分配器和比较运算符来实现的,因为 std::allocator 和 std::less 是无状态的。(只要自定义分配器/比较运算符是无状态的,也会为它们启用这些优化。显然,无法避免有状态的分配器/比较运算符的存储,但这种情况极为少见。)

Visual Studio 2013 中的 Visual C++ 超越了 C++11 来实现一些关键的 C++14 库功能:

  • “透明运算符函子”less<>greater<>plus<>multiplies<> 等。

  • make_unique(args...) 和 make_unique(n)

  • cbegin()/cend()rbegin()/rend() 和 crbegin()/crend() 非成员函数。

你可能感兴趣的:(VS2010、VS2012、VS2013对C++11的支持进度)