February 28, 2021
Hot Topics:

C++ Language Changes for Visual Studio 2005

  • By Kate Gregory
  • Send Email »
  • More Articles »

Destructors and Finalizers

What happens when you write a garbage-collected object that can be used by other languages, and you've written a destructor for it? When you're working from C++, you can create that object on the stack, and the destructor will run when it goes out of scope. What happens when a C# or VB application (which cannot create garbage-collected objects on the stack) uses that object? The runtime takes care of this in a very neat way. It exposes your destructor as a Dispose() method. So any C++/CLI object that has a destructor is disposable.

If you've written a class in C# or VB that has a Dispose() method, you've probably also written a finalizer. C++/CLI has a convenience syntax for finalizers, too. Just as the destructor for Foo is called ~Foo(), the finalizer for Foo is called !Foo(). (That's the kind of gentle humor that really works for me: ~ is a bitwise NOT, and ! is a logical NOT. Both of them remind you that they are the opposite of the constructor.)

The finalizer runs when an object is created on the managed heap and never disposed (because most Dispose implementations suppress the finalizer). It's a backstop to make sure your object cleans up the unmanaged resources it holds, even if the consumers of the object forget to dispose it.

Pointers and Handles

In managed extensions for C++, because a major restriction was that the language not change, the same punctuation and syntax was used for two very different things. The meaning of * depended on some other information from another place in your code. Try it yourself. Look at this line:

Foo* pf = new Foo();

Where is the Foo object created? Is that memory going to be cleaned up or not? Can I do some arithmetic with that pointer, like this:


The answer depends on whether Foo was declared with the __gc keyword or not. If it's a garbage-collected object, it can be created only on the managed heap—not the native heap, not the stack. On the other hand, if it was not declared with __gc, this line is allocating the memory on the native heap, and you have to remember to clean it up with delete later.

Once the compiler writers have the freedom to change the language, as has happened with C++/CLI, you can decouple what kind of class it is from where it lives. You can also signal where it lives by using different syntax:

Foo^ hf = gcnew Foo();

This is called a handle, and most of the C++ team seem to pronounce that symbol "caret or hat" the first time, and "hat" from then on. You dereference handles with * or ->, just like pointers. The impact of this change is mostly in your head. You can see how lifetime issues are managed just from the declaration of the instance, without having to go back and look at the declaration of the class.

Speaking of the declaration of the class, __gc and __nogc are gone. In their place are some cool "spaced keywords." A spaced keyword appears to be two keywords but is actually one word that happens to contain a space. For example:

ref class R
   int m_a;
   R(int a): m_a(a) {}

You might think "ref" is a new keyword in C++/CLI, but it's not. "Ref class" is the keyword. You can have a variable called ref that won't cause any kind of conflict. Other spaced keywords include "value class", "interface class", and "enum class". Because almost every C++ program ever written contains a variable called "value", I'm really glad that "value" did not become a keyword.

A ref class is a managed class, a class designed to live on the managed heap and be managed by the garbage collector. You can create instances on the stack if you like, as I showed earlier. The compiler will look after that for you, essentially making an invisible smart pointer.


There's more in C++ property changes—a lot more. But, because I started the column with an illustration of the awkwardness of properties in Managed C++, let me close with the much neater version in C++/CLI:

ref class R
   int m_Size;
   property int Size
      int get()  { return m_Size; }
      void set(int val){m_Size = val;}
R r;
r.Size = 42;

Is property a keyword? Sort of. It's a positional keyword, so you can have a variable or function called property without a conflict. It carries special meaning only in a class definition, as shown here. Now, the C++/CLI language supports the idea of a property definition as a single unit. I like this a lot better than the old way, and I believe you will too.

Keep Reading

The entire language specification is on the Web at http://download.microsoft.com/download/9/9/c/99c65bcd-ac66-482e-8dc1-0e14cd1670cd/C++%20CLI%20Candidate%20Base%20Draft.pdf, if you just have to read it. I'll be coming back to more examples of the syntax changes as we move through the pre-release and beta cycle for Visual Studio 2005. A new Community Technical Preview was released at Tech Ed, so you can play with the new syntax, or at least the parts that have been implemented so far. (Put these bits on a spare computer you wouldn't mind reformatting.) Check http://msdn.microsoft.com/vs2005/preview/default.aspx for updates.

About the Author

Kate Gregory is a founding partner of Gregory Consulting Limited (www.gregcons.com). In January 2002, she was appointed MSDN Regional Director for Toronto, Canada. Her experience with C++ stretches back to before Visual C++ existed. She is a well-known speaker and lecturer at colleges and Microsoft events on subjects such as .NET, Visual Studio, XML, UML, C++, Java, and the Internet. Kate and her colleagues at Gregory Consulting specialize in combining software develoment with Web site development to create active sites. They build quality custom and off-the-shelf software components for Web pages and other applications. Kate is the author of numerous books for Que, including Special Edition Using Visual C++ .NET.

Page 2 of 2

This article was originally published on June 11, 2004

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