The Evolution of Visual C++ in Visual Studio 2010
With the release of Visual Studio 2010, several improvements have been made to make life easier for C++ developers. The three areas of focus for Visual C++ 2010 include a better programming model, overall performance and productivity, and support for Windows 7 applications with an updated MFC Library.
Specifically, Visual Studio 2010 enables a more modern programming model by adding core C++ language features from the upcoming C++0x standard and overhauling the standard library to take advantage of the new language features. There are new parallel programming libraries and tools to simplify the creation of parallel programs.
Visual Studio 2010 has made great strides in performance and developer productivity. The new Windows Presentation Foundation (WPF)-based IDE is more extensible, has a new look and feel, and has been designed to improve readability. Document windows such as code editor and design view windows can now float outside the main IDE window and can be displayed on multiple monitors.
For C++ developers, IntelliSense and code-browsing features now scale to projects with millions of lines of code without compromising on performance. The build system and project system have migrated to MSBuild and offer better customizability and extensibility. Finally, code-generation improvements in the back-end of the Visual C++ compiler enable better performance and code quality.
In this article, I'll take a closer look at these core enhancements to Visual Studio 2010 and explain how these language features, updated libraries and tools can benefit C++ developers.
C++0x Core Language Features
Visual Studio 2010 gives developers powerful new core language features from the upcoming C++0x standard. The Visual C++ compiler in Visual Studio 2010 has enabled six C++0x core language features: lambda expressions, auto keywords, rvalue references, static_assert, nullptr and decltype.
Lambdas are a core language feature that have lightweight natural syntax to define function objects where they're used, and these expressions have no performance overhead. Function objects are a very powerful way to customize the behavior of Standard Template Library (STL) algorithms and can encapsulate both code and data (unlike plain functions). In C++ development, lambda expressions implicitly define and construct unnamed function objects.
Auto keyword is now used to automatically determine the type of a variable from its initializer. Auto reduces verbosity and helps important code stand out; it also helps make code more generic by allowing you to write templates without having to worry about the types of intermediate expressions.
C++0x has introduced a new kind of reference type called rvalue references. Rvalue references help solve the problem of unnecessary copying and enable perfect forwarding. This reference type enables move semantics. When the right-hand side of an assignment is an rvalue, then the left-hand side object can steal resources from the right-hand side object rather than performing a separate allocation. Perfect forwarding allows you to write a single function template that takes N arbitrary arguments and forwards them transparently to another arbitrary function. For a more detailed discussion on rvalue references, check out the MSDN documentation on the topic here.
Static_assert allows you to test assertions during compile time, rather than at execution time. Static assertions enable you to trigger compiler errors with custom error messages that are easy to read; they're especially useful for validating template parameters.
Nullptr keyword has been introduced in this release to help developers avoid difficult-to-diagnose failures in perfect forwarding functions. Nullptr is a constant, which is convertible to any pointer type, but no other type (for example, int or char). In addition to being used in the perfect forwarding functions, this new nullptr can be used anywhere the macro NULL was used as a null pointer.
Decltype is a language feature that allows the compiler to infer the return type of a function based on an arbitrary expression and makes perfect forwarding more generic. In past versions, for two arbitrary types T1 and T2 there was no way to deduce the type of an expression that used these two types. The decltype allows you to state things like an expression that has template arguments, such as: sum<T1, T2>() has the type of T1+T2.
Standard Library Improvements
Substantial portions of the standard C++ library have been rewritten in Visual Studio 2010 to take advantage of the new C++0x language features and increase performance.
In particular, adoption of rvalue references has yielded many benefits. Types such as vector and list now have move constructors and move assignment operators of their own. For example, vector reallocations exploit move semantics by picking up move constructors.
Therefore, if your types have move constructors and move assignment operators, the library will recognize that information automatically. The C++0x function template make_shared<T>() has been added to the standard library. You can now make a shared pointer to an object at the same time that you're constructing the object:
auto sp = make_shared<T>(args);
This provides you with a more convenient, robust and efficient way to use a shared pointer.
The standard library now provides you with a new pointer type unique_ptr that can be used in place of auto_ptr and allows you to implement strict ownership semantics without affecting safety. This release includes a number of new algorithms proposed in various C++0x papers, such as min/max element, iota and is_sorted.
Additionally, a small set of conversion libraries has been included in the standard library, which will allow developers to do conversions such as UTF-8 to UTF-16 with ease.
Also, many of the TR1 features that existed in namespace std::tr1 in the previous release, such as shared_ptr and regex, have now been made part of the standard library and have been moved under namespace std.
New Concurrency Runtime and Libraries
Visual Studio 2010 introduces the Parallel Computing Platform, which helps you write high-performance parallel code quickly while avoiding subtle concurrency bugs. This lets you avoid some of the classic problems faced with concurrency.
The Parallel Computing Platform has four major parts: the Concurrency Runtime (ConcRT), the Parallel Patterns Library (PPL), the Asynchronous Agents Library, and parallel debugging and profiling tools.
The concepts of tasks, the PPL and the Asynchronous Agents Library provide you with a programming model to approach writing parallel code more elegantly. These libraries are based on the new ConcRT, which is included within the Visual C++ runtime. The mapping between tasks and execution threads -- and ensuring that all the cores are optimally utilized -- is managed by ConcRT, which is the lowest software layer that talks to the operating system and arbitrates between multiple concurrent components competing for resources.
Any computation that can be decomposed into sub-computations can be implemented using tasks. For example, sorting two halves of an array can be done by two different tasks concurrently. Even the simple concept of threads takes you away from your problem domain by making you think about the hardware, OS and critical sections. Task is an abstraction that's much closer to your problem domain. Tasks are first-class concepts in parallel algorithms, classes and containers included in PPL.
Additionally, the Asynchronous Agents Library gives you a dataflow-based programming model where computations are dependent on the required data becoming available. The library is based on the concepts of agents, message blocks and message-passing functions. An agent is a component of an application that does certain computations and communicates asynchronously with other agents to solve bigger computation problems. This communication between agents is achieved via the message-passing functions using message blocks to help avoid issues that arise from the use of shared memory in concurrent applications.
Support for parallel debugging and profiling in Visual Studio 2010 makes it easier to debug concurrency issues. The debugger includes new tool windows to visualize the state of all tasks in an application. The concurrency profiler tool allows you to visualize the behavior of parallel applications.
IntelliSense and Design-Time Productivity
A brand new IntelliSense and browsing infrastructure is included in Visual Studio 2010. In addition to helping with scale and responsiveness on projects with large code bases, the infrastructure improvements have enabled building some fresh design-time productivity features.
IntelliSense features such as live error reporting and quick info tooltips are based upon a new compiler front-end. It parses the full translation unit to provide you with rich and accurate information about code semantics, even while the code files are being modified.
All the code-browsing features, like class view and class hierarchy, now use the source code information stored in a SQL database that enables indexing and has a fixed memory footprint. Unlike previous releases, the Visual Studio 2010 IDE is always responsive and you no longer have to wait while compilation units get reparsed when changing a header file.
The IntelliSense live error reporting is a new feature added in this release. The editor displays compiler-quality syntax and semantic errors during browsing and editing of code, without doing a build. A wavy underline (squiggle) is displayed at the location of the error, and the tool tip shows the error message, as shown in Figure 1. The error list window also shows this error, as well as the Intelli-Sense errors from elsewhere in the current compilation unit.
[Click on image for larger view.]
|Figure 1. In Visual Studio 2010, live error reporting shows loss of IntelliSense at the location of the error and with a tool tip message. |
Another new feature to increase your productivity with file or symbol search is Navigate To, under the Edit menu or using the shortcut "Ctrl+comma." This feature gives you real-time search results (based on substrings as you type) matching your input strings across any project. It also works for C# and Visual Basic projects, and is extensible.
Developers also get Auto Complete help for include statements in Visual Studio 2010. A list of relevant include files is displayed in a drop-down while typing #include, and the list will refine as you type and help you add the right include files with less typing. Call
Hierarchy -- an improved version of Call Browser -- provides you with the calls to and calls from trees for any function in the same window. Inactive code now retains the semantic information by maintaining colorization, instead of becoming gray.
Note that while all the code-browsing features are available for both pure C++ and C++/CLI, IntelliSense-related features like live error reporting and Quick Info will not be available for C++/CLI in the final release of Visual Studio 2010. We're working on adding full IntelliSense support for C++/CLI in the future.
Build and Project Systems
Visual Studio 2010 also offers substantial improvements in the build system and the project system for C++ projects.
The most important change is that MSBuild is now used to build C++ projects. MSBuild is an extensible, XML-based build orchestration engine that has been used for C# and Visual Basic projects in previous versions of Visual Studio. MSBuild is now the common Microsoft build system for all languages. It can be used both in the build lab as well as on individual developer machines.
C++ build processes are now defined in terms of MSBuild target and task files and provide you a greater degree of customizability, control and transparency.
The C++ project type now has a new extension: .VCXPROJ.
Visual Studio will automatically upgrade old .VCPROJ files and solutions to the new format. There's also a command-line tool, vcupgrade.exe, to upgrade single projects from the command line.
In the past, you only had the option of using the toolset -- the compiler and libraries -- that came with that particular version of Visual Studio. Visual Studio 2010 solves that problem by allowing you to target a different version of the toolset -- for example, the Visual C++ 9.0 version of compiler and libraries from Visual Studio 2010 -- while being able to take advantage of all the new productivity features. This functionality is known as native multi-targeting.
You can also extend the default build system by adding a tool or build step. This is especially useful for creators of libraries and tools. The Project system, which sits on top of the Build system, leverages the extensibility provided to it by MSBuild. It allows you to surface your customizations in the project system UI, enabling developers to configure those customizations in the same way that they can configure C++ compiler settings in the property pages. You can also configure a project system to use your own platform, similar to the existing x86 or x64 platforms, or your own debugger.
MSBuild provides better diagnostic information to make it easier for you to debug build problems. This also makes incremental builds more reliable. Plus, you can create build systems that are more closely tied to source control and build lab, and are less dependent on the developer machine configuration.
Faster Compilation and Better Performance
In addition to the design-time experience improvements described so far, Visual Studio 2010 also improves the compilation speed, quality and performance for applications built with the Visual C++ compiler. The compiler back-end has added multiple code-generation enhancements to bring these improvements.
The performance of certain applications depends on the working set. The code size for the x64 architecture has been reduced in the range of 3 percent to 10 percent by making multiple optimizations in this release, which has resulted in a performance improvement for such applications.
Single Instruction Multiple Data code generation -- which is important for game, audio, video and graphics developers -- has been optimized for better performance. Breaking false dependencies, vectorization of constant vector initializations, and better allocation of XMM registers to remove redundant loads, stores and moves are all improvements that have been introduced in this release.
For improved performance, applications should be built using Link Time Code Generation (LTCG) and Profile Guided Optimization (PGO). Compilation with LTCG usually takes longer than non-LTCG compilation, especially in large applications. In Visual Studio 2010 the LTCG compilation has been improved by up to 30 percent.
PGO instrumentation runs have been made faster by adding support for no-lock versions of instrumented binaries. There's also a new POGO option, PogoSafeMode, which enables you to specify whether to use safe mode or fast mode when you optimize an application. Fast mode is the default behavior. Safe mode is thread-safe, but slower than fast mode.
A dedicated thread to write .PDB files has been introduced in this release, so you'll see link time improvements when you use the /DEBUG switch. Also, the quality of compiler-generated code has been improved. There's now full support for Advanced Vector Extensions (AVX) that are very important for floating-point-intensive applications in AMD and Intel processors via intrinsic and /arch:AVX options. Floating point computation is more precise with /fp:fast option.
Build Great Applications on Windows 7
Windows 7 has introduced a number of exciting technologies and features. You can take advantage of innovations like Direct3D 11, DirectWrite, Direct2D and Windows Web Service APIs by using the SDK headers and libraries available in Visual Studio 2010.
In addition to making all the Windows APIs available to developers, this release of Visual Studio gives you access to Windows 7 functionality through updated MFC libraries. Your existing MFC applications will light up on Windows 7 just by recompiling, and your new applications will be able to take full advantage of the new Windows 7 features. For example, your application's integration with Windows Explorer can now be better optimized by making use of file handlers for preview, thumbnails and search. Taking advantage of previews, thumbnails and the search indexer provided by Windows is as easy as selecting these options in the MFC Application Wizard. Your application will be able to show rich thumbnails and previews in Windows Explorer. MFC provides this capability without you having to write a single additional line of code.
One of the most noticeable UI changes in Windows 7 is the new Taskbar. MFC allows developers to quickly take advantage of features such as jump lists, tabbed thumbnails, thumbnail preview, progress bar and icon overlay, as shown in Figure 2.
[Click on image for larger view.]
|Figure 2. The updated MFC library allows developers to take advantage of thumbnail previews and tabbed thumbnails in Windows 7 for a tabbed MDI MFC application.|
The Ribbon UI now has a Windows 7-style ribbon as well. MFC enables applications to become multi-touch-aware and calls appropriate messages for you to handle when the various touch events occur. Your application can register to inform MFC that it's interested in touch and gesture events, and MFC will take care of appropriately routing those events for your application. MFC also makes applications high-DPI aware by default. Therefore, your applications will adapt to high-DPI screens and won't look pixilated or fuzzy. MFC internally scales and changes fonts to make sure the UI continues to look sharp on high-DPI displays.
In addition to some of the new Windows 7 features, Visual Studio 2010 supports features that have existed since Windows Vista but were not included in previous releases of MFC. For example, Restart Manager is a very useful feature introduced in Vista that enables an application to perform an application save before terminating, and can re-invoke the application and restore its state from before shutdown. You can now take full advantage of Restart Manager in your MFC application to handle crashes and restarts more elegantly. Another addition is the Task Dialog, which is an improved version of message box. MFC now has a wrapper for Task Dialog.
Functionality has been added in MFC, and this release also makes it easier to work with the library in the IDE. One of the most commonly requested features, MFC Class Wizard, has been brought back from Visual Studio 6.0 and improved. You can easily add classes and event handlers in your application using MFC Class Wizard.
Additionally, this release has introduced a rich Ribbon designer while also making the Ribbon itself an XML resource rather than code, as it was in the previous release.
[Click on image for larger view.]
|Figure 3. The popular MFC Class Wizard -- which lets developers visually add classes, messages and variables to MFC projects -- is back in Visual Studio 2010.|
Visual Studio 2010 is a major release in the evolution of Visual C++. Whether it's the improved productivity with large code bases, the introduction of C++0x language features, support for parallel coding or the opportunity to write modern Windows 7 applications, Visual Studio 2010 has a lot to offer a C++ developer.
For further discussion on different features, please refer to the MSDN documentation and to the Visual C++ Team's blog at blogs.msdn.com/vcblog, which was also used as the basis for some of the sections in this article. A more detailed version of this article will also be published in the April issue of MSDN magazine.
Sumit Kumar is a program manager in the Visual C++ IDE team. He holds a Master of Science degree in Computer Science from the University of Texas at Dallas.