C++11函数(现代C++)
本文档描述功能新 C++ 标准也称为 C++11 在 Visual C++ 中实现。
C++11 核心语言功能
Visual C++ 2010 实现了 C++0x 核心语言规范的许多功能,是前体 C++11,并且,Visual Studio 2012 中的 Visual C++ 在该扩展包含许多 C++11 功能。 下表列出了 C++11 核心语言功能及其实现的状态。Visual C++ 2010 和 Visual Studio 2012 中的 Visual C++。
VC10 |
VC11 |
|
---|---|---|
v2.0 |
v2.1* |
|
否 |
否 |
|
否 |
否 |
|
否 |
否 |
|
否 |
否 |
|
是 |
是 |
|
v1.0 |
v1.0 |
|
是 |
是 |
|
v1.0 |
针对 |
|
v1.0 |
针对** |
|
是 |
是 |
|
否 |
否 |
|
否 |
否 |
|
否 |
否 |
|
是 |
是 |
|
是 |
是 |
|
Partial |
是 |
|
否 |
是 |
|
否 |
否 |
|
否 |
否 |
|
TR1 |
Partial |
|
否 |
否 |
|
否 |
否 |
|
否 |
否 |
|
否 |
否 |
|
否 |
否 |
|
否 |
否 |
|
否 |
否 |
|
否 |
否 |
|
否 |
是 |
|
否 |
否 |
|
是 |
是 |
|
否 |
否 |
|
否 |
否 |
|
否 |
否 |
|
是 |
是 |
|
否 |
是 |
|
Partial |
是 |
|
是 |
是 |
|
否 |
否 |
C++11 核心语言功能:并发 |
VC10 |
VC11 |
---|---|---|
不可用 |
不可用 |
|
否 |
是 |
|
否 |
是 |
|
否 |
是 |
|
不可用 |
不可用 |
|
否 |
是 |
|
否 |
否 |
|
是 |
是 |
|
否 |
否 |
|
否 |
否 |
|
Partial |
Partial |
|
否 |
否 |
C++11 核心语言功能:C99 |
VC10 |
VC11 |
---|---|---|
Partial |
Partial |
|
Partial |
Partial |
|
是 |
是 |
|
不可用 |
不可用 |
这是对信息的一种快速准则表中。
Rvalue 引用
N1610“选件类对象的初始化声明由 rvalues” 是一个早期尝试启用移动语义不 rvalue 引用。 在本讨论中,我们称之为“rvalue 引用 v0.1”。它由“取代 rvalue 引用 v1.0”。“Rvalue 引用 v2.0”,正是在 Visual C++ 2010 的工作开始,禁止 rvalue 从绑定到 lvalue 从而解决主安全问题引用。“ Rvalue 引用 v2.1“优化此规则。 考虑 vector<string>::push_back(),具有超负载 push_back(const string&) 和 push_back(string&&)和调用 v.push_back("strval")。 该表达式 "strval" 是字符串写入,因此,它是 lvalue。 (其他文本,如将整数 1729,这是 rvalues,但是,字符串写入是特定的,因为它们是数组。)rvalue 引用 v2.0 规则显示,string&& 不能绑定到 "strval",因为 "strval" 是 lvalue,因此,push_back(const string&) 是唯一的可行超负载。 这将创建临时 std::string,将其复制到向量,然后销毁临时 std::string。 这不是非常高效。 rvalue 引用 v2.1 规则识别该绑定 string&& 到 "strval" 将创建临时 std::string,因此,该临时是 rvalue。 因此,push_back(const string&) 和 push_back(string&&) 可行的,因此,push_back(string&&) 首选方法。 临时 std::string 构造,然后将该矢量。 这是更有效。
在特定条件下“Rvalue 引用 上述”添加新规则集自动生成移动构造函数和移动赋值运算符。 但是,这在 Visual Studio 2012 中的 Visual C++未实现,因为时间和资源约束。
警告
v0.1,v1.0,v2.0,v2.1,上述标识符为清楚起见进行开发并显示 C++11. 的发展。
Lambdas
在 lambda 函数 轮询到工作文件 (版本 0.9) 之后,并且变量的 lambda 已添加 (版本 1.0),标准化可将实质上已字词。 这将产生了 lambda 版本 1.1。 这在 Visual C++ 2010太后发生合并,但是,它在 Visual Studio 2012 中的 Visual C++。 lambda 的字词阐明了在角用例应发生希望引用静态成员或嵌套 lambda。 此修复由复杂 lambda 触发的 bug。 此外,在 Visual Studio 2012 中的 Visual C++无状态的 lambda 转换为函数指针。 这不在 N2927 字词,但是,它无论 + 如何计数为 lambda 的一部分。 FDIS 5.1.2 [expr.prim.lambda]/6 具有此声明:,当关闭类型的函数调用运算符,“的 lambda 表达式的类型不关闭 lambda 捕获有一个公共非虚拟非显式常量转换函数指针传递给具有的功能相同参数和返回类型。 此转换函数返回的值是函数的地址,那么,当调用,其效果和调用关闭类型相同的函数调用运算符”。( Visual Studio 2012 中的 Visual C++ 相比,好,因为我们使无状态的 lambda 转换函数具有任意调用约定的指针。 这是重要的,在使用需要与 __stdcall 函数指针的内容。) 的 API 时
decltype
在 decltype 轮询到工作文件 (版本 1.0) 后,它最后一刻接收小,但重要的 bug 修复 (版本 1.1)。 这是了感兴趣在 STL 和引发工作的程序员。
强类型/向前声明枚举
强类型的枚举 在 Visual C++ 2010 (特别是,有关显式指定的基础类型的部分部分支持)。 Visual Studio 2012 中的 Visual C++ 完全实现,他们完全实现 C++11 语义 前向声明枚举。
对齐方式
Visual C++ 2010 和 Visual Studio 2012 中的 Visual C++ 实现核心语言关键字 alignas/从轮询到工作文件的 对齐建议alignof。 Visual C++ 2010 具有从 TR1 的 aligned_storage。 Visual Studio 2012 中的 Visual C++ 添加 aligned_union 和 std::align() 到标准库。
标准格式和常用的类型
显示的更改从 N2342“重新访问的 POD 的;解决的问题 568 核心 (版本 5)” 是 is_trivial 和 is_standard_layout 的向 <type_traits>。 (N2342 修改了大量核心语言,字词,但编译器没有必需的更改。)这些类型特征可在 Visual C++ 2010,但是,它们复制 is_pod。 因此,表之前文档中显示“不支持”。 在 Visual Studio 2012 中的 Visual C++,它们被设计为精确的答案编译器挂钩关闭。
重写和最终
这通过短,但复杂的发展。 最初, 版本 0.8,[[override]], [[hiding]] 以及 [[base_check]] 特性。 然后,版本 0.9属性使用上下文关键字消除并替换。 最后,版本 1.0它们减少到“final”在选件类和“override”和“final在函数。 这使它成为个 ascending 的扩展,因为 Visual C++ 2010 已经支持函数中的此“override”语法,并具有语义合理关闭会 C++11。“ final”还支持,但是,在其他拼写“下方密封了”。 在 Visual Studio 2012,“override”和“final”标准拼写和语义完全支持。 有关更多信息,请参见override 说明符和final 说明符。
Atomics 和更多
Atomics,强请比较和交换,双向范围,数据依赖项排序 然后指定标准库前,在 Visual Studio 2012 中的 Visual C++实现。
标准库函数
该报告核心语言。 有关 C++11 标准库,我们不具有一个以美观的表,但是,Visual Studio 2012 中的 Visual C++ 实现该接口,有两个异常。 首先,那么,当库功能取决于缺少在编译器的功能时,我们可模拟它要求 (例如,我们模拟 make_shared<T>()的 variadic 模板 (或我们不实现该接口存在,特别是,只在少数情况下 <initializer_list>。 接下来,C99 标准库,将对 C++11 标准库,主要未实现,不过,<stdint.h> 在 Visual C++ 2010实现的。 这是部分列出了 Visual Studio 2012 中的 Visual C++中的更改:
新标头:<atomic>,<chrono>、<condition_variable>、<future>、<mutex>、<ratio>、<scoped_allocator>和 <thread>。
根据 C++11,emplace()/emplace_front()/emplace_back()/emplace_hint()/emplace_after() 的建立: 在“参数的任意”数字 (请参见“虚假 variadics”部分) 的任何容器实现。 例如,vector<T> 具有“直接构造元素类型 T 在矢量的返回从任意数量的任意参数的,完全转发的template <typename... Args> void emplace_back(Args&&... args)。 这比 push_back(T&&)可以高效,将包括额外的移动构造和析构。
**虚假 variadics:**Visual Studio 2012 中的 Visual C++ 具有模拟的 variadic 模板新架构。 在 Visual C++ 2008 SP1 和 Visual C++ 2010,subheaders 重复包括了不同的每次生成定义的宏,灭绝 0,1,2,3,或多个参数的超负载。 例如,<memory> 重复包含内部 subheader <xxshared>,灭绝 make_shared<T>(args, args, args)。 在 Visual Studio 2012 中的 Visual C++,subheaders 转到。 现在 variadic 模板定义为宏 (与许多杠继续) 通过母版宏,然后展开。 此内部实现更改具有这些效果:
代码更易于维护,更易于使用 (添加 subheaders 适合数量的工作),和可读性。
单步执行与调试器抱歉更难!
std::pairpair(piecewise_construct_t, tuple<Args1...>, tuple<Args2...>) 构造函数具有“有趣的”效果。 这需要 N^2 超加载 (如果我们支持到 10 元组,该太意味着 121 超负载,因为空元组计数此处,)。
发送相同的消息到多个按组许多对元组超负载,和任何建立超负载,在编译时已占用大量内存。 因此,我们减少了无穷大。 在 Visual C++ 2008 SP1 和 Visual C++ 2010,不是 10 (即“variadic”模板支持 0 到 10 个参数,包含)。 默认情况下,不是 5 在 Visual Studio 2012 中的 Visual C++。 这使编译器内存消耗回什么是在 Visual C++ 2010。 如果需要更多参数 (例如,因此,如果您具有使用 6 元组) 的现有代码,所以紧急导出。 可以定义 _VARIADIC_MAX 项目在 5 和 10 之间包含。 将占用太多内存,并可能需要使用 /Zm 编译器选项保留多个空格预先生成标头的。
**随机性:**uniform_int_distribution 现已完成公平的,因此,shuffle() 在 <algorithm>实现,直接接受与 mersenne_twister的统一随机数生成器。
对重载的抵抗 address-of 运算符: C++98/03 禁止 STL 容器的元素重载其地址运算符。 这就是"类别。CComPtr 执行,因此,需要与 CAdapt 的帮助器类选件防止这种超加载的 STL。 在 Visual C++ 2010的开发过程中,STL 更改使其拒绝重载地址更情况的运算符。 C++11 更改了要求使重载 address-of 运算符可接受。 C++11 和 Visual C++ 2010,提供帮助器函数 std::addressof(),而不管运算符重载,可以获取对象真实地址。 在发布之前 Visual C++ 2010,我们将尝试用“std::addressof(elem)”替换“&elem”显示时,正确有吸引力。 在 Visual Studio 2012 中的 Visual C++,我们进一步转到。 现在我们审核的所有容器和所有迭代器,因此,这些重载运算符地址的选件类应可在 STL 中。
Visual Studio 2012 中的 Visual C++ 超过 C++11 范围的方法有多种:
可怕迭代器: 如允许使用,但不要求由标准的 C++11,可怕迭代器实现,如中所述 “将泛型选件类中的依赖项 N2911 更快、更小程序的” 和 N2980“可怕迭代分配和初始化,版本 1 "。
文件系统:<filesystem> 标头从 TR2 建议 已添加。 它提供 recursive_directory_iterator 和其他有趣的功能。 在 TR2 的工作冻结之前,因为 C++0x 非常后运行并更改为 C++11,该 2006 年建议从 + 中派生的 Boost.Filesystem V2。 它后面转变为 Boost.Filesystem V3,但这在 Visual Studio 2012 中的 Visual C++未实现。
和一个母版优化! 我们的容器现在最好较小的给定的所有其当前表示。 这表示为其容器对象,而不指向内容。 例如,std::vector 包含三个基元的指针。 在 Visual C++ 2010,x86 版本的模式,std::vector 为 16 字节。 在 Visual Studio 2012 中的 Visual C++,它是 12 个字节,最好较小的。 这很大,事务如果您有 100,000 个矢量在您的程序,Visual Studio 2012 中的 Visual C++ 将为您节省 400,000 字节。 减少内存使用量节省空间和时间。
这是通过避免 null 的分配器和比较存储实现,因为 std::allocator 和 std::less 是无状态的。 (这些优化为自定义分配器/比较器启用,前提是无状态的。 显然,监视状态的分配器/比较器存储不能避免,但是,某些非常少见。)
容器大小
下表列出了字节显示容器的边界,x86 和 x64 平台的。 (32 位 ARM 与这些目的 x86 等效)。 这些桌帷发布模式,因为调试模式包含检查占用空间和时间的很多。 不同的列是 Visual C++ 2008 SP1,_SECURE_SCL 默认为 1,并且,对于 Visual C++ 2008 SP1 和 _SECURE_SCL 手动设置为 0 最大速度。 Visual C++ 2010 和 Visual Studio 2012 中的 Visual C++ 默认 _SECURE_SCL 到 0 (现在称为 _ITERATOR_DEBUG_LEVEL)。
x86 容器大小 (字节) |
VC9 SP1 |
VC9 SP1 SCL=0 |
VC10 |
VC11 |
---|---|---|---|---|
向量<int> |
24 |
16 |
16 |
12 |
数组<int, 5> |
20 |
20 |
20 |
20 |
向量、双端队列<int> |
32 |
32 |
24 |
20 |
forward_list<int> |
不可用 |
不可用 |
8 |
4 |
列表<int> |
28 |
12 |
12 |
8 |
priority_queue<int> |
28 |
20 |
20 |
16 |
队列<int> |
32 |
32 |
24 |
20 |
堆栈<int> |
32 |
32 |
24 |
20 |
对<int, int> |
8 |
8 |
8 |
8 |
元组<int, int, int> |
16 |
16 |
16 |
12 |
映射<int, int> |
32 |
12 |
16 |
8 |
基于<int, int> |
32 |
12 |
16 |
8 |
设置<int> |
32 |
12 |
16 |
8 |
多级集<int> |
32 |
12 |
16 |
8 |
hash_map<int, int> |
72 |
44 |
44 |
32 |
hash_multimap<int, int> |
72 |
44 |
44 |
32 |
hash_set<int> |
72 |
44 |
44 |
32 |
hash_multiset<int> |
72 |
44 |
44 |
32 |
unordered_map<int, int> |
72 |
44 |
44 |
32 |
unordered_multimap<int, int> |
72 |
44 |
44 |
32 |
unordered_set<int> |
72 |
44 |
44 |
32 |
unordered_multiset<int> |
72 |
44 |
44 |
32 |
string |
28 |
28 |
28 |
24 |
wstring |
28 |
28 |
28 |
24 |
x64 容器大小 (字节) |
VC9 SP1 |
VC9 SP1 SCL=0 |
VC10 |
VC11 |
---|---|---|---|---|
向量<int> |
48 |
32 |
32 |
24 |
数组<int, 5> |
20 |
20 |
20 |
20 |
向量、双端队列<int> |
64 |
64 |
48 |
40 |
forward_list<int> |
不可用 |
不可用 |
16 |
8 |
列表<int> |
56 |
24 |
24 |
16 |
priority_queue<int> |
56 |
40 |
40 |
32 |
队列<int> |
64 |
64 |
48 |
40 |
堆栈<int> |
64 |
64 |
48 |
40 |
对<int, int> |
8 |
8 |
8 |
8 |
元组<int, int, int> |
16 |
16 |
16 |
12 |
映射<int, int> |
64 |
24 |
32 |
16 |
基于<int, int> |
64 |
24 |
32 |
16 |
设置<int> |
64 |
24 |
32 |
16 |
多级集<int> |
64 |
24 |
32 |
16 |
hash_map<int, int> |
144 |
88 |
88 |
64 |
hash_multimap<int, int> |
144 |
88 |
88 |
64 |
hash_set<int> |
144 |
88 |
88 |
64 |
hash_multiset<int> |
144 |
88 |
88 |
64 |
unordered_map<int, int> |
144 |
88 |
88 |
64 |
unordered_multimap<int, int> |
144 |
88 |
88 |
64 |
unordered_set<int> |
144 |
88 |
88 |
64 |
unordered_multiset<int> |
144 |
88 |
88 |
64 |
string |
40 |
40 |
40 |
32 |
wstring |
40 |
40 |
40 |
32 |
快速参考到 Visual C++ 版本号的准则
Visual C++ 具有不同的“版本号”基于您找到的位置。 一个带有品牌的版本 (打印在框中),内部版本 (如 有关 对话框) 和编译器版本 (显示由 cl.exe 和 _MSC_VER 宏)。
带有品牌的版本号 |
内部版本号 |
#define _MSC_VER 版本号 |
---|---|---|
Visual C++ 2005 |
VC8 |
1400 |
Visual C++ 2008 |
VC9 |
1500 |
Visual C++ 2010 |
VC10 |
1600 |
Visual Studio 2012 中的 Visual C++ |
VC11 |
1700 |
_MSC_VER 宏是有趣到面向 Visual C++ 不同的主版本和发出它们的其他代码的人。