Archive for the 'review' Category

14
Nov
12

C++ Basics: Static

I’ve been working on this long, boring post about the differences in equality comparison in Perl and Python and the fundamental differences of the two languages, but you know what? I’m sick of Perl and Python! And that post was boring! So let’s talk about C++ instead.

I’m in the unenviable position of not having touched a compiler (for work) in about a year. How do you live, Maitland?, you ask, Without C++, what gives your life meaning? Those are really wonderful questions for another blog, but the fact is, while I’ve learned tons in the last year about Perl and automation (and debugging and debugging and debugging), my C++ knowledge has been getting fuzzier and fuzzier. It’s extremely unnerving. Just yesterday, I opened up one of my favorite books and I freaked out because I saw my second favorite* C++ keyword, static, and, frankly, I wasn’t sure I could remember all of its usage. Thank god I have a blog so I can write it all down.

The static keyword can be the slightest bit tricky because it has several applications, and different implications in different situations. Some people will tell you that it behaves differently or that it means something different in these different situations, but I feel like this point of view overcomplicates the issue. From my point of view, static really just means one thing: it means that for the duration of the program, there will be only one of the described object or function. Once the thing is defined, it’s defined for the lifetime of the program. In fact, static objects don’t even allocate memory from the stack or the heap — they have their own separate memory segment, creatively called static memory.

Static Objects. Static non-member objects are probably the simplest usage of static. They look like this:

static int myInt = 42;

Once this variable is initialized, it’s there for the lifetime of the program. So if, for example, you put this variable in a header file, you can change that object in your functions or class members, and the change will persist. The example above uses an integer, but the concept is the same for user-defined types as well. Static objects are scoped in the same way that any other object is. If the object is declared in a header, it is scoped by the translation unit (i.e., the source and headers required to compile a given source file) that includes it. If it’s declared inside a method or function, like any local variable, it cannot be referenced outside of that method or function.

Static Members. A static member is much like a static object except for the fact that it belongs to a class. A static member is shared by all instances of a class. The biggest implication of this is that you can modify the member completely independently from an instance of the class. For example,

class MyClass
{
public:
  static int m_myInt;
}

MyClass::m_myInt = 0;

is totally valid code! Furthermore, any instances of MyClass can modify that member, and that change will persist until some other instance (or external code) modifies that member. Obviously, making a static non-const member public is fairly dangerous (as is making any member variable public), because you have no way of controlling who can modify it, but a non-public member can be very useful when you want to keep a reference count of something, for example. And when you combine static and const, you have a great way to store immutable data that may want to be scoped and defined at compile time.

One thing worth pointing out about static members is that, unless they are const and integral, you cannot initialize them within the class declaration. Logically, this makes sense, when you consider that you could construct the class multiple times, and, if the static member were initialized within the declaration, it would theoretically be re-initialized every time the class was instantiated. Because a static member is defined for all instances of a class, re-defining it in every instance would violate C++’s one definition rule. (C++ does make an exception for static const integral members, but if I’m being honest, I don’t entirely understand the rationale except “it makes life easier,” which, in fairness, is a good thing.)

Static Methods. Static methods (not to be confused with static functions!) have a lot in common with static members. Like static members, they can be referenced without an instance of the class. The natural implication of this is that static methods cannot reference any non-static members of the class. Because they don’t require state, static methods are especially good when you have software that uses callbacks. They allow you to group functionality with your class even when that functionality does not operate on the class’s state directly.

Static LinkageOkay, here’s where it gets a little tricky. Remember how I said that static really only means one thing? I kinda lied.

So, a long time ago, in a galaxy far, far away, there was a little programming language called C. And it defined static as a keyword, and it was slightly really a lot different from how C++ defines it. If you define (not declare) a method or function as static, the compiler, knowing that it has to be backwards compatible with C, treats this as static linkage. This means that your function or method cannot be referenced outside of the file it’s defined in. I’m sure there are good reasons to do this — certainly, it allows you to write helper functions that you don’t intend to be used outside of a certain file — but I can’t say I’ve ever used it myself.

I feel like I must be forgetting something, but I suppose that’s to be expected, given how rusty I am. Hell, I haven’t even talked about extern or referenced Meyer’s excellent point about how the intialization order of non-local static objects is totally undefined, meaning you should probably avoid that and use a local static variable inside a function instead. But this is getting lengthy, so I think I’ll close it off here. Next time, memory segments?

* My favorite being, of course, const.




About

My name is Maitland Lederer, and I’m a video game developer. I learn stuff you probably already knew and have opinions you've probably already heard. I figured it might be a good idea for me to start writing down the stuff I've learned so I don't have to relearn it. It's not, like, great wisdom or anything. It's just things I happened to learn, usually today.

Header photo by D Sharon Pruitt, used under a Creative Commons License.