C++11 Features (Modern C++)
This document describes the features of the new C++ Standard—also known as C++11—that are implemented in Visual C++.
C++11 Core Language Features
Visual C++ 2010 implemented many features in the C++0x core language specification, which was the precursor to C++11, and Visual C++ in Visual Studio 2012 expands on that to include many C++11 features. The following table lists C++11 core language features and their implementation status in both Visual C++ 2010 and Visual C++ in Visual Studio 2012.
VC10 |
VC11 |
|
---|---|---|
v2.0 |
v2.1* |
|
No |
No |
|
No |
No |
|
No |
No |
|
No |
No |
|
Yes |
Yes |
|
v1.0 |
v1.0 |
|
Yes |
Yes |
|
v1.0 |
v1.1 |
|
v1.0 |
v1.1** |
|
Yes |
Yes |
|
No |
No |
|
No |
No |
|
No |
No |
|
Yes |
Yes |
|
Yes |
Yes |
|
Partial |
Yes |
|
No |
Yes |
|
No |
No |
|
No |
No |
|
TR1 |
Partial |
|
No |
No |
|
No |
No |
|
No |
No |
|
No |
No |
|
No |
No |
|
No |
No |
|
No |
No |
|
No |
No |
|
No |
Yes |
|
No |
No |
|
Yes |
Yes |
|
No |
No |
|
No |
No |
|
No |
No |
|
Yes |
Yes |
|
No |
Yes |
|
Partial |
Yes |
|
Yes |
Yes |
|
No |
No |
C++11 Core Language Features: Concurrency |
VC10 |
VC11 |
---|---|---|
N/A |
N/A |
|
No |
Yes |
|
No |
Yes |
|
No |
Yes |
|
N/A |
N/A |
|
No |
Yes |
|
No |
No |
|
Yes |
Yes |
|
No |
No |
|
No |
No |
|
Partial |
Partial |
|
No |
No |
C++11 Core Language Features: C99 |
VC10 |
VC11 |
---|---|---|
Partial |
Partial |
|
Partial |
Partial |
|
Yes |
Yes |
|
N/A |
N/A |
Here's a quick guide to the information in the tables.
Rvalue References
N1610 "Clarification of Initialization of Class Objects by rvalues" was an early attempt to enable move semantics without rvalue references. For the sake of this discussion, let’s call it "rvalue references v0.1." It was superseded by "rvalue references v1.0." "Rvalue references v2.0", which is what the work in Visual C++ 2010 was based on, prohibits rvalue references from binding to lvalues and thereby fixing a major safety problem. "Rvalue references v2.1" refines this rule. Consider vector<string>::push_back(), which has the overloads push_back(const string&) and push_back(string&&), and the call v.push_back("strval"). The expression "strval" is a string literal, and it is an lvalue. (Other literals, for example the integer 1729, are rvalues, but string literals are special because they are arrays.) The rvalue references v2.0 rules said, string&& cannot bind to "strval" because "strval" is an lvalue, and therefore, push_back(const string&) is the only viable overload. This would create a temporary std::string, copy it into the vector, and then destroy the temporary std::string. This wasn’t very efficient. The rvalue references v2.1 rules recognize that binding string&& to "strval" would create a temporary std::string, and that temporary is an rvalue. Therefore, both push_back(const string&) and push_back(string&&) are viable, and push_back(string&&) is preferred. A temporary std::string is constructed, and then moved into the vector. This is more efficient.
"Rvalue references v3.0" adds new rules to automatically generate move constructors and move assignment operators under certain conditions. However, this is not implemented in Visual C++ in Visual Studio 2012, due to time and resource constraints.
Warning
The v0.1, v1.0, v2.0, v2.1, v3.0 designations are invented for clarity and to show the evolution of C++11.
Lambdas
After lambda functions were voted into the Working Paper (version 0.9) and mutable lambdas were added (version 1.0), the Standardization Committee overhauled the wording. This produced lambdas version 1.1. This occurred too late to be incorporated in Visual C++ 2010, but it is in Visual C++ in Visual Studio 2012. The lambdas v1.1 wording clarifies what should occur in corner cases like referring to static members or nested lambdas. This fixes bugs that are triggered by complex lambdas. Additionally in Visual C++ in Visual Studio 2012, stateless lambdas are convertible to function pointers. This is not in the N2927 wording, but it is counted as part of lambdas v1.1 anyway. FDIS 5.1.2 [expr.prim.lambda]/6 has this description: "The closure type for a lambda-expression with no lambda-capture has a public non-virtual non-explicit const conversion function to pointer to function having the same parameter and return types as the closure type’s function call operator. The value returned by this conversion function shall be the address of a function that, when invoked, has the same effect as invoking the closure type’s function call operator." (The Visual C++ in Visual Studio 2012 is even better than that, because we've made stateless lambdas convertible to function pointers that have arbitrary calling conventions. This is important when you are using APIs that expect things like __stdcall function pointers.)
decltype
After decltype was voted into the Working Paper (version 1.0), it received a small but important bug fix at the last minute (version 1.1). This is of great interest to programmers who work on the STL and Boost.
Strongly Typed/Forward Declared enums
Strongly typed enums were partially supported in Visual C++ 2010 (specifically, the part about explicitly specified underlying types). Visual C++ in Visual Studio 2012 fully implements them, and also fully implements the C++11 semantics for forward declared enums.
Alignment
Neither Visual C++ 2010 nor Visual C++ in Visual Studio 2012 implement the Core Language keywords alignas/alignof from the alignment proposal that was voted into the Working Paper. Visual C++ 2010 had aligned_storage from TR1. Visual C++ in Visual Studio 2012 adds aligned_union and std::align() to the Standard Library.
Standard-Layout and Trivial Types
The exposed changes from N2342 "POD's Revisited; Resolving Core Issue 568 (Revision 5)" are the additions of is_trivial and is_standard_layout to <type_traits>. (N2342 reworked a lot of the Core Language wording, but no compiler changes are necessary.) These type traits were available in Visual C++ 2010, but they just duplicated is_pod. Therefore, the table earlier in this document said "No" support. In Visual C++ in Visual Studio 2012, they are powered by compiler hooks that are designed to give accurate answers.
override and final
This went through a short but complicated evolution. Originally, in version 0.8, there were [[override]], [[hiding]], and [[base_check]] attributes. Then in version 0.9, the attributes were eliminated and replaced with contextual keywords. Finally, in version 1.0, they were reduced to "final" on classes, and "override" and "final" on functions. This makes it an Ascended Extension because Visual C++ 2010 already supported this "override" syntax on functions, and had semantics reasonably close to those in C++11. "final" was also supported, but under the different spelling "sealed". In Visual Studio 2012, the Standard spelling and semantics of "override" and "final" are completely supported. For more information, see override Specifier and final Specifier.
Atomics, and More
Atomics, strong compare and exchange, bidirectional fences, and data-dependency ordering specify Standard Library machinery, which are implemented in Visual C++ in Visual Studio 2012.
Standard Library Features
That covers the Core Language. As for the C++11 Standard Library, we don't have a pretty table of features, but Visual C++ in Visual Studio 2012 does implement it, with two exceptions. First, when a library feature depends on functionality that's missing in the compiler, we either simulate what it requires—for example, we simulate variadic templates for make_shared<T>()—or we don't implement it—there are only a few cases, most notably, <initializer_list>. Second, the C99 Standard Library, which is incorporated by reference into the C++11 Standard Library, is mostly unimplemented, although <stdint.h> was implemented in Visual C++ 2010. Here's a partial list of the changes in Visual C++ in Visual Studio 2012:
New headers:<atomic>, <chrono>, <condition_variable>, <future>, <mutex>, <ratio>, <scoped_allocator>, and <thread>.
Emplacement: As required by C++11, emplace()/emplace_front()/emplace_back()/emplace_hint()/emplace_after() are implemented in all containers for "arbitrary" numbers of arguments (see the "Faux variadics" section). For example, vector<T> has "template <typename... Args> void emplace_back(Args&&... args)" which directly constructs an element of type T at the back of the vector from an arbitrary number of arbitrary arguments, perfectly forwarded. This can be more efficient than push_back(T&&), which would involve an extra move construction and destruction.
Faux variadics: Visual C++ in Visual Studio 2012 has a new scheme for simulating variadic templates. In Visual C++ 2008 SP1 and Visual C++ 2010, subheaders were repeatedly included with macros defined differently every time, to stamp out overloads for 0, 1, 2, 3, or more arguments. For example, <memory> included the internal subheader <xxshared> repeatedly, to stamp out make_shared<T>(args, args, args). In Visual C++ in Visual Studio 2012, the subheaders are gone. Now variadic templates themselves are defined as macros (with lots of backslash-continuations), and then expanded by using master macros. This internal implementation change has these effects:
The code is more maintainable, easier to use (adding subheaders was a fair amount of work), and more readable.
It's harder to step into with the debugger—sorry!
The pair(piecewise_construct_t, tuple<Args1...>, tuple<Args2...>) constructor of std::pair had "interesting" effects. This requires N^2 overloads (if we support up to 10-tuples, that means 121 overloads, because empty tuples count here, too).
Spamming out so many pair-tuple overloads, plus all of the emplacement overloads, consumed a massive amount of memory during compilation. Therefore, we reduced infinity. In Visual C++ 2008 SP1 and Visual C++ 2010, infinity was 10 (that is, "variadic" templates supported 0 to 10 arguments, inclusive). By default, infinity is 5 in Visual C++ in Visual Studio 2012. This brings compiler memory consumption back to what it was in Visual C++ 2010. If you need more arguments (for example, if you have existing code that uses 6-tuples), there is an escape hatch. You can define _VARIADIC_MAX project-wide between 5 and 10 inclusive. This consumes more memory, and may require that you use the /Zm compiler option to reserve more space for pre-compiled headers.
**Randomness:**uniform_int_distribution is now perfectly unbiased, and shuffle() is implemented in <algorithm>, which directly accepts Uniform Random Number Generators like mersenne_twister.
Resistance to overloaded address-of operators: C++98/03 prohibited an element of an STL container from overloading its address-of operator. This is what classes like CComPtr do, so that helper classes like CAdapt were required to shield the STL from such overloads. During the development of Visual C++ 2010, STL changes made it reject overloaded address-of operators in even more situations. C++11 changed the requirements to make overloaded address-of operators acceptable. C++11, and Visual C++ 2010, provide the helper function std::addressof(), which can get the true address of an object regardless of operator overloading. Before Visual C++ 2010 was released, we attempted to replace occurrences of "&elem" with "std::addressof(elem)", which is appropriately resistant. In Visual C++ in Visual Studio 2012, we've gone further. Now we've audited all containers and all iterators, so that classes that overload their address-of operator should be usable throughout the STL.
Visual C++ in Visual Studio 2012 goes beyond C++11 in several ways:
SCARY iterators: As permitted but not required by the C++11 Standard, SCARY iterators have been implemented, as described by N2911 "Minimizing Dependencies within Generic Classes for Faster and Smaller Programs" and N2980 "SCARY Iterator Assignment and Initialization, Revision 1".
Filesystem: The <filesystem> header from the TR2 proposal has been added. It offers recursive_directory_iterator and other interesting features. Before work on TR2 was frozen because C++0x was running very late and was changing to C++11, the 2006 proposal was derived from Boost.Filesystem V2. It later evolved into Boost.Filesystem V3, but that's not implemented in Visual C++ in Visual Studio 2012.
And a major optimization! All of our containers are now optimally small given their current representations. This refers to the container objects themselves, not to their pointed-to contents. For example, std::vector contains three raw pointers. In Visual C++ 2010, x86 release mode, std::vector was 16 bytes. In Visual C++ in Visual Studio 2012, it is 12 bytes, which is optimally small. This is a big deal—if you have 100,000 vectors in your program, Visual C++ in Visual Studio 2012 will save you 400,000 bytes. Decreased memory usage saves both space and time.
This was achieved by avoiding the storage of empty allocators and comparators, because std::allocator and std::less are stateless. (These optimizations are enabled for custom allocators/comparators too, as long as they are stateless. Obviously, storage of stateful allocators/comparators cannot be avoided, but those are very rare.)
Container Sizes
The following tables show the container sizes, in bytes, for x86 and x64 platforms. (32-bit ARM is equivalent to x86 for these purposes). These tables cover release mode, because debug mode contains checking machinery that consumes space and time. The separate columns are for Visual C++ 2008 SP1, where _SECURE_SCL defaulted to 1, and for Visual C++ 2008 SP1 with _SECURE_SCL manually set to 0 for maximum speed. Visual C++ 2010 and Visual C++ in Visual Studio 2012 default _SECURE_SCL to 0 (now known as _ITERATOR_DEBUG_LEVEL).
x86 Container Sizes (Bytes) |
VC9 SP1 |
VC9 SP1 SCL=0 |
VC10 |
VC11 |
---|---|---|---|---|
vector<int> |
24 |
16 |
16 |
12 |
array<int, 5> |
20 |
20 |
20 |
20 |
deque<int> |
32 |
32 |
24 |
20 |
forward_list<int> |
N/A |
N/A |
8 |
4 |
list<int> |
28 |
12 |
12 |
8 |
priority_queue<int> |
28 |
20 |
20 |
16 |
queue<int> |
32 |
32 |
24 |
20 |
stack<int> |
32 |
32 |
24 |
20 |
pair<int, int> |
8 |
8 |
8 |
8 |
tuple<int, int, int> |
16 |
16 |
16 |
12 |
map<int, int> |
32 |
12 |
16 |
8 |
multimap<int, int> |
32 |
12 |
16 |
8 |
set<int> |
32 |
12 |
16 |
8 |
multiset<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 Container Sizes (Bytes) |
VC9 SP1 |
VC9 SP1 SCL=0 |
VC10 |
VC11 |
---|---|---|---|---|
vector<int> |
48 |
32 |
32 |
24 |
array<int, 5> |
20 |
20 |
20 |
20 |
deque<int> |
64 |
64 |
48 |
40 |
forward_list<int> |
N/A |
N/A |
16 |
8 |
list<int> |
56 |
24 |
24 |
16 |
priority_queue<int> |
56 |
40 |
40 |
32 |
queue<int> |
64 |
64 |
48 |
40 |
stack<int> |
64 |
64 |
48 |
40 |
pair<int, int> |
8 |
8 |
8 |
8 |
tuple<int, int, int> |
16 |
16 |
16 |
12 |
map<int, int> |
64 |
24 |
32 |
16 |
multimap<int, int> |
64 |
24 |
32 |
16 |
set<int> |
64 |
24 |
32 |
16 |
multiset<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 |
Quick Reference Guide to Visual C++ Version Numbers
Visual C++ has different "version numbers" depending on where you look. There's the branded version (printed on the box), the internal version (displayed in the About dialog box), and the compiler version (displayed by cl.exe and the _MSC_VER macro).
Branded version number |
Internal version number |
#define _MSC_VER version number |
---|---|---|
Visual C++ 2005 |
VC8 |
1400 |
Visual C++ 2008 |
VC9 |
1500 |
Visual C++ 2010 |
VC10 |
1600 |
Visual C++ in Visual Studio 2012 |
VC11 |
1700 |
The _MSC_VER macro is interesting to people who want to target different major versions of Visual C++ and emit different code for them.
See Also
Reference
Range-based for Statement (C++)
Other Resources
Welcome Back to C++ (Modern C++)