Static Constructors in Managed C++

I have a pet peeve. I hate to read "C++ doesn't have <some feature> but C# does." Or sometimes it's worded "<some feature>, which was always missing from C++, is now in C#." These annoy me because, while they are technically true, they are not usefully true. The feature under discussion may not be part of Standard C++, but if it's part of Managed C++, why go to C# to have it? If you're willing to target the .NET Framework and write a managed application, why not write in Managed C++? And every time I've checked, the feature that C# has "over" C++ is, in fact, available in Managed C++.

Take static constructors, for example. It's easy to find blogs and articles that will tell you C++ doesn't have them. And that's true, Standard C++ doesn't have them. But Managed C++ does. And that's good news for library writers.

What's a Static Constructor?

A static constructor is also called a type constructor. Like the ordinary kind of constructor, it's called "behind-the-scenes" by the compiler, and can't be called by you. But, instead of being called whenever an instance of your class is created (by a stack allocation, a heap allocation with new, or when some temporary objects are created for function parameters or return values), a static constructor is called the first time a static member variable in your class is used. Then, it is never called again. Its purpose is to initialize your static member variables.

Life Without Static Constructors

So, imagine that you write a class library, and it has a class in it like this:

(Your code, of course, would be far more interesting, but interesting code tends to drown out language features, so I've spent years now writing methods that add two numbers, reverse strings, and the like. It's an art, really.) This code uses two static variables, x and y, that hold numbers used in internal calculations. Those variables are initialized at declaration, in some file that will only be compiled once (that is, not a header file):

int UsefulThings::x=2;
int UsefulThings::y=6;

If you're not planning to ever change the values of x and y, you could make them const and initialize them right in the class definition, which is convenient:

But, what if x and y are not const at all? You might want to initialize them but then go on to change them over the lifetime of your program. Well, in that case, you have to use the "separate declaration in a .cpp file" approach. It feels a little awkward, but you get used to it.

Does anything change if you decide to make UsefulThings a managed class? Absolutely. For one thing, you can initialize those static member variables to literals right in the class definition, like this:

In this version of UsefulThings, x and y are not const and can be changed at will.

Initializing Your Library

Sometimes, the initial values of your static member variables can't be known at compile time. Perhaps you need to read a value from a file, or get it from a database. You want to run some code that initializes the static variable. The tried and true approach is to write a function for this, and teach everyone to call the initializing method before they call any other methods that rely on the static variables:

What happens if someone using your library doesn't remember to call Initialize() before the first call that (directly or indirectly) uses the static member variables on UsefulThings? If you forget to initialize a static member variable, it is initialized to zero. That's not a terribly useful value, but at least you don't get whatever bits of junk were in that memory location from the last time someone used it. I would prefer if you got some sort of exception to remind you that you were making a mistake. You could add a little error checking to the class by having a flag that Initialize() set to 1, and adding code to all the functions that threw an exception if the flag were 0. Keep that in mind if you're writing an unmanaged library. For managed libraries, there's a better way.

Initializing with a Static Constructor

If you think way back to before C++, to programming in C, one of the major annoyances was having to remember to do things. Open the file before you read from it the first time. Allocate memory the first time you work with this struct. Call function1 before you call function2. That was one of the big appeals of C++: you could write a constructor that initialized all the member variables, allocated memory, opened things, and generally took care of making your object ready to use.

If you're writing a class library, you might not want to make your library functions into ordinary member functions and force people to create an instance of the UsefulThings class before they can call library methods. You can see, though, that if you did, there would be a constructor involved, and that constructor could take the place of Initialize(). Lots of class libraries take this approach. You can even leave x and y as static member variables so that, no matter how many instances of UsefulThings are created, they all share the same values for those variables. Those instances will still take up space, and there is a performance cost to create them and clean them up, but many developers were willing to make that tradeoff to get libraries that were self-initializing.

When you make a managed class library, you can get that self-initializing behavior without forcing anyone to create an instance. The secret is a static constructor. The CLR takes care of running the constructor exactly once, before any of the static member variables are touched and before any instances of the class are created. A static constructor looks just like a regular constructor with the word static thrown in:

This is very convenient and elegant. The library takes care of itself and the calling programmer doesn't have to remember anything in order to use it properly. It fits nicely with the spirit of C++. If you're writing a managed library, and you were planning on having an initializing function, why not use a static constructor instead?

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.

IT Solutions Builder
TOP IT RESOURCES TO MOVE YOUR BUSINESS FORWARD

Which topic are you interested in?

Mobile

Security

Networks/Iot

Cloud

Data Storage

Application

Development

IT Management

Other

What is your company size?

What is your job title?

What is your job function?

Searching our resource database to find your matches...

Please enable Javascript in your browser, before you post the comment! Now Javascript is disabled.