January 27, 2021
Hot Topics:

C++/CLI: Managed Development with C++

  • By Nick Wienholt
  • Send Email »
  • More Articles »

The C++ language supports a number of different programming paradigms—functions and structures support procedural programming, classes, virtual methods, and other related features support object-orientated program, and templates support generic programming. C++/CLI extends the C++ language to allow it to support managed programming, where the classes that are developed are garbage collected and have their lifetime managed by the .NET runtime. The syntax of C++/CLI makes a clear break from standard C++ syntax of object creation and deletion, and makes it very clear that the objects are created and managed by the .NET runtime. In combination with the language changes, the C++ compiler can now generate .NET assemblies that are verifably type-safe, which makes them easier to deploy in Internet and intranet scenarios.

C++/CLI: The Basics

Visual C++ 2008 supports a number of different types of C++/CLI projects, as shown in Figure 1. Noticeably absent is any type of web projects—the reason behind this is incompatibilities in the C++ and ASP.NET 2 compilation models. Outside of this restriction, Visual C++ gives a wide variety of development options, and it is possible to use business logic contained in a C++/CLI class library in an ASP.NET website written in C# or Visual Basic.NET.

Click here for a larger image.

Figure 1: CLR C++ Project Types

The most striking part of C++/CLI is the explicitness of its syntax compared to Managed Extensions for C++. Consider the following code, which allocates a managed string and creates a reference to the managed string from the variable s.

String^ s = gcnew String("123");

There are two obvious deviations from normal C++ syntax: the pointer (*) syntax is replaced by a managed object handle (^), and the new keyword has been replaced by gcnew. Both of these syntactic changes make it very clear to the developer that a managed object is being created and used, and the stricter rules for object handles compared to pointers allow accurate object tracking to occur, which makes garbage collection possible.

To declare a managed type in C++/CLI, the context-sensitive ref keyword is used:

ref class  MyManagedClass{};
ref struct MyManagedStruct{};

The compiler will prevent managed objects from being created on the native heap using by the new operator, and will also prevent native objects from being created on the managed heap using the gcnew operator. Similarly, a compiler error will also be generated if pointer and object handle syntax is used incorrectly.

Even in a managed environment, resource cleanup is still an important issue, and C++/CLI offers a clean, simple syntax to create types that manage resources like database connection handles and window handles that are not managed by garbage collection. C++/CLI uses destructor syntax to implement the Dispose method and uses ! syntax to mark the finalize method of a class:

ref class MyManagedClass{
   ~MyManagedClass(){}     //dispose
   !MyManagedClass() {}    //finalize

Dispose methods are called by other code to let an object know that it should clean up the resources it is holding. If the code that is using a managed object forgets to call the Dispose method to free the resources being held, the Finalize method is the back up, and will be called at some later point in time as part of the garbage collection process. The one key difference between the implementation of the Dispose and Finalize methods is that Dispose methods can safely access other managed objects that they reference and also free their resources, whereas a Finalize implementation should deal only with native resources that are held directly by the object. Given the uncertain time delay between the final use of an object and the time that the .NET runtime will execute the Finalize method, explicit object Disposal is preferable.

C++/CLI: Cool Features

One of the most common criticisms of Managed Extensions for C++ was that is didn't feel like C++. Although it was C++ syntactically, the semantics of how the code worked was very different from the normal native C++ language. One of the most obvious differences was the loss of deterministic resource cleanup. As discussed in the preceding section, the .NET garbage collector will deal with managed memory cleanup, but the multitude of other resource types that require manual cleanup still need the same developer attention and discipline that they do in the native world.

In languages such as C# and Visual Basic.NET, resource cleanup is a significant problem because there is no concept of stack-based allocation, so the problem of calling the Dispose method manually to release resources is left to developers to call for every IDisposable-implementing object, even if the native resources are needed only within the scope of a method. Even though the using statement goes some way to addressing this problem, it still requires that the developer looks up the documentation for every type used and checks whether it implements IDisposable. C++/CLI takes a different approach, and logically separates heap- and stack-based allocation of managed objects in the same way that native C++ physically separates these two concepts. C++/CLI allows both value and reference types to be stack allocated using the same syntax as normal C++, so for the MyManagedClass type shown above, both lines of code below are valid:

MyManagedClass c1;
MyManagedClass^ c2 = gcnew MyManagedClass();

Page 1 of 2

This article was originally published on October 6, 2008

Enterprise Development Update

Don't miss an article. Subscribe to our newsletter below.

Thanks for your registration, follow us on our social networks to keep up-to-date