Introduction
Visual Studio 11 Beta was made available at the end of February. Ignoring the commonly disliked chrome theme, the new version of Visual Studio provides lots of improvements, both for managed and native development. In this article, I will enumerate and discuss some of the new or improved features for native development (but not all). These include improved or new features in the C++11 language support, the compiler and linker, the VC++ libraries and the IDE. A complete list of these features is available in MSDN. VS11 beta can be downloaded from here.
No Windows XP Support
Before discussing what's new, I must stress a very important point: VS11 does not support Windows XP and Windows Server 2003 anymore. Native applications built with VS11 will no longer run on WinXP/Server2003 because the VC++ libraries (CRT and MFC) use system APIs that are only available starting with Vista. The minimum supported operating systems are Windows Server 2008 SP2 and Windows Vista. An item on Microsoft Connect targets this problem.
Mike Ryan has written a blog post about getting your statically linked VS11 native application run on Windows XP, by wrapping the required missing APIs and making an assembly language forwarding directive that calls them. His tutorial is available here.
C++11 Support
VS11 extends the C++ compiler's support for C++11, but not everything is yet implemented. However, they have promised to deliver updated support to core features after the release of VS11, probably in the form of a feature pack. This blog post from the VC++ Team contains a table with the support for C++11 features in VS10 and VS11. The new features in VS11 include:
- forward declared
enum
s and full support for strongly typed enum
- standard-layout and trivial types
- range-based
for
loops override
and final
- concurrency features: reworded sequence points, atomics, strong compare and exchange, bidirectional fences and data-dependency ordering
Strongly Typed Enums
Regular C++ enumerations export their enumerators to the surrounding scope. This has two drawbacks. First, it can lead to name clashes, if two enumerators in different enum
s declared in the same scope have the same name; second, it's not possible to use an enumerator with a fully qualified name, including the enum
name. These issues have been addressed in the new standard which provides a new kind of enum
, introduced with "enum
class" and called strongly-typed enum
s. They no longer export their enumerators to the surrounding scope, can have user specified underlying type of an integral type (also added for tranditional enum
s) and do not convert implicitly to int
.
enum class Options {None, One, All};
Options o = Options::All;
Forward declaration of enum
s allows declaring enum
s before they are defined.
enum class Options;
void make_selection(Options* op);
enum class Options {None, One, All};
An article on strongly typed enum
s can be found here.
Range-Based for Loops
Writing (for
) loops over a range of values didn't use to be very friendly in C++. All major languages used to have a way to make this simpler, but not C++. C++11 introduces range-based for
loops that have a simple syntax for iterating arrays or containers. It looks like this:
int arr[] = {1,2,3,4,5};
for(int i : arr)
cout << i << " ";
You can even substitute the type and use the auto
keyword, which is especially helpful when you work with STL containers (and you might have something like map<int, vector<string>>
).
for(auto i : arr)
cout << i << " ";
In this example, the variable 'i
' is read-only. You cannot change its value. If you want to change the content, you can use a reference.
for(auto &i : arr)
i *= i;
The new range-based for
loops work with arrays, string
s and STL containers, but also with any user-defined data structure provided that your iterator:
- has a
begin()
and end()
method operating on your custom data structure - has an operator*, operator != and operator++ (the prefix version)
An example on how to write such an iterator can be found in this article.
Override and Final
Earlier, C++ didn't have a method to specify that a virtual
method in a derived class overrides a method from the base class. In fact, the virtual
keyword is optional on the derived class, which makes this even more confusing. It is possible to make mistakes when writing virtual
methods. Let's take, for instance, this example:
class B
{
public:
virtual void f(int) {cout << "B::f" << endl;}
};
class D : public B
{
public:
virtual void f(float) {cout << "D::f" << endl;}
};
The f()
method in class D
does not override the method with the same name in B
, because the argument is of another type. The following example is also wrong, because B::f
is const
, and D::f
is not, therefore it's not an override.
class B
{
public:
virtual void f(int) const {cout << "B::f " << endl;}
};
class D : public B
{
public:
virtual void f(int) {cout << "D::f" << endl;}
};
C++11 provides the possibility to specify that a method is indented to override a base virtual
method. This is achieved by marking a method with 'override
'. This is not a keyword, but a special identifier, and it can be used elsewhere as an identifier.
class B
{
public:
virtual void f(int) {cout << "B::f" << endl;}
};
class D : public B
{
public:
virtual void f(float) override {cout << "D::f" << endl;}
};
The code above generates the following compiler error:
error C3668: 'D::f' : method with override specifier 'override'
did not override any base class methods
On the other hand, it is possible that you do not want a method to be further overridden in the hierarchy. The special identifier 'final
' (not a keyword) can be used to mark a function as such. The following example generates an error.
class B
{
public:
virtual void f(int) final {cout << "B::f" << endl;}
};
class D : public B
{
public:
virtual void f(int) override {cout << "D::f" << endl;}
};
error C3248: 'B::f': function declared as 'final' cannot be overridden by 'D::f'
Bjarne Stroustrup discusses more about override and final on his C++11 FAQ page.
C++ Compiler Enhancements: Auto-vectorizor and Auto-parallelizer
So far, the C++ compiler only used the scaler unit from the CPU. However, nowadays, all CPUs have a vector unit too (see SSE on Wikipedia). These contain vector registers that can perform operations on vectors (a sequence of numbers) in a single instruction. That means if you have a loop where data doesn't carry dependencies (like a loop that performs a summation), it could be actually executed with the vector instructions (of course, given some constrains are met), making the execution time be several times smaller. The C++ compiler in VS11 has been enhanced to take advantage of the SIMD instructions and auto-vectorize the loops it finds safe. This is enabled by default and requires no changes to your code. Given the particularities of your program, it can provide a significant implicit boost.
Besides SSE support, nowadays most CPUs are also multi-core, which means multiple vector units. Therefore in addition to the auto-vectorization, the VS11 C++ compiler can also do an auto-parallelization, spreading the computation on multiple cores. The auto-parallelizer is very conservative and in the current version will find few cases where the loops can be auto-parallelized. However, developers can instruct the compiler to auto-parallelize a loop by using <tt>pragma loop(hint_parallel(N))</tt>
. The auto-parallelizer is not enabled by default on VS11. You have to go to your project's properties, C/C++ > Code Generation and set "Enable Parallel Code Generation" to "Yes", or use /Qpar if you build from a command line.
Jim Radigan and Jim Hogg provide insights into the auto-vectorizor and the auto-parallelizer in this channel9 interview.
IDE Enhancements
C++/CLI IntelliSense
In VS2010, the VC++ team has re-designed the IntelliSense, but VS2010 shipped without any IntelliSense support for C++/CLI projects (this VC++ Team blog post explains why). This has been a major complain and the good news is that VS11 comes with IntelliSense support for C++/CLI. That means features like Quick Info, Parameter Help, List Members and Auto Completion do work properly with C++/CLI.
C++ Code Snippets
Code snippets are small blocks of reusable code that you can insert in your code (such as a switch
or a try
-catch
block). They have been available for a while, but not for C++. VS11 now provides C++ code snippets for switch
, if
-else
, for
loop and other constructs. In addition, developers can define their own snippets. This article by Ovidiu Cucu shows how to do that.
Semantic Colorization
I've been always annoyed by the IDE's inability to colorize C++ code. I was nicely surprised to see VS11 has finally done something about it. The new IDE is able to colorize by default types, enum
s, macros and other C++ tokens. More about that here.
Parallel Libraries
Microsoft delivered with Visual Studio 2010 two C++ libraries for native parallel programming, one called Parallel Patterns Library (or simply PPL) used for writing task parallelism, and a second one called Asynchronous Agents Library used for expressing dataflows and pipelining tasks using an actor-based programming model and message passing. In VS11, these libraries were extended to provide better performance, more control and richer support for the most used parallel patterns.
The PPL library becomes even more relevant with Windows 8 and WinRT that offers a new programming model in which all blocking operations are asynchronous. PPL makes it easier for developers to write C++ async code (though not as easy as in C#), where continuations, a new feature to the library, plays a key role. This Asynchronous Programming in C++ Using PPL article by Artur Laksberg addresses this topic.
VS11 introduces a new library (announced last summer) called C++ Accelerated Massive Parallelism (or simply C++ AMP). This is a native library built on top of DirectX that allows developers to write parallel code that runs on heterogeneous hardware. It aims to make GPU programming easy for C++ developers. It provides multidimensional arrays, indexing, memory transfer, tiling, and a mathematical function library, while language extensions and compiler restrictions can be used to control how data moves between the CPU and GPU. A C++ AMP "Hello world
" application can be found here.
Lots of information and examples can be found on the blog of the team that implemented these libraries.
Little MFC Updates
VS11 doesn't bring any updates to MFC, except mainly for a series of bug fixes (including paint/draw issues or memory leaks) as explained by Pat Brenner in this blog post. The only significant change was reducing the size of statically-linked MFC applications that use "MFC controls". These are the controls that are part of the feature pack delivered to MFC in Visual Studio 2008 and that are prefixed with "MFC" (such as CMFCButton
, CMFCListCtrl
, CMFCToolbar
, CMFCMenuBar
, etc.). In Visual Studio 2010, statically-linked MFC applications that use such controls had a dramatic increase in size. This was fixed for VS11, though changes could not be propagated back to Visual Studio 2010 because it would have broken existing code. The solution is to define _AFX_NO_MFC_CONTROLS_IN_DIALOGS
in your application if you do not use such controls. In this case, your application will be linked with a new, smaller version of the library that has the same methods, but different implementation. If at any point, you need to add MFC controls, you just remove that macro without any other code changes. Of course, in this case, the application would be linked to the regular library implementation and the size would increase. This blog post provides the details of the problem and the solution.
The lack of investment in MFC is not something unexpected, given the company's push for Windows 8, WinRT and Metro style-applications. Unfortunately, this will probably be the case for all future releases. I believe MFC will no longer benefit from any enhancements other than bug fixes and maybe some header updates once in a while.
Windows 8
Windows 8 is the new flag ship of the company and VS11 provides great support for building C++ applications for the new Windows runtime, called WinRT. (This is also the reason why there are no important updates to MFC.) WinRT is still a native runtime. The applications built for WinRT are called Metro-style applications. The great part about it is that the same API is exposed to C++, C#/VB.NET and JavaScript.
Microsoft has built an extension to C++, called C++ Component eXtensions, or simply C++/CX. It is the language used to author native components or applications for WinRT. It has a very similar syntax to C++/CLI, though there are some differences, and unlike the C++/CLI which targets the CLR, C++/CX targets WinRT and native code. For more information on this topic, read Nish Sivakumar's Visual C++ and WinRT/Metro - Some fundamentals.
In VS11, it is possible to:
- build Metro-style applications in C++ using the new native XAML framework or DirectX; it is actually possible to use both of them in the same application, the two operate efficiently.
- build WinRT components for Metro-style apps written with C++, HTML5/JabaScript or .NET.
When you install VS11 on Windows 8, you get some additional Windows Metro style templates. These are not available on the other systems, because WinRT is not available on the previous operating systems.
Here is a classic "Hello world!
" C++ application using the native XAML framework for the UI. There is basically no C++ code (other than what the wizard generated for this type of project). There is a slider on the top and a block of text displaying "Hello world
". The font size of the text block is bound to the value of the slider. Everything is done in XAML.
<Page
x:Class="HelloWorldApp.BlankPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:HelloWorldApp"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">
<Grid Background="{StaticResource ApplicationPageBackgroundBrush}">
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition Height="15*"/>
</Grid.RowDefinitions>
<Slider Name="slider" Minimum="20" Maximum="80"
Value="50"
Grid.Row="0" />
<TextBlock Text="Hello world!"
FontSize="{Binding ElementName=slider, Path=Value, Mode=OneWay}"
HorizontalAlignment="Center"
Grid.Row="1" />
</Grid>
</Page>
Conclusion
VS11 brings significant improvements or new features for native developers. These include new features from C++11 (although more are expected after the RTM), updates to the VC++ libraries, improvements to the VC++ compiler, new features in the IDE for C++, support for building Windows 8 Metro-style applications and others. On the other hand, there are very few improvements in MFC and, very important, no support for Windows XP and Windows Server 2003. If your native applications still target these operating systems, you won't be able to use the new toolset to build them.
History
- 5th April, 2012: Initial version
Marius Bancila is the author of Modern C++ Programming Cookbook and The Modern C++ Challenge. He has been a Microsoft MVP since 2006, initially for VC++ and nowadays for Development technologies. He works as a system architect for Visma, a Norwegian-based company. He works with various technologies, both managed and unmanaged, for desktop, cloud, and mobile, mainly developing with VC++ and VC#. He keeps a blog at http://www.mariusbancila.ro/blog, focused on Windows programming. You can follow Marius on Twitter at @mariusbancila.