You are on page 1of 5

Home

Why C++?
What It's All About
By Kyle Wilson
Who Is This Guy? Saturday, July 15, 2006

The List A number of different on-line forums (most notably the SWEng-
GameDev mailing list) have seen recent discussion of whether C++ is a
Complete Archive wise language choice for game development. When people have to make
that decision in the real world, the dominance of C++ has been
Personal overwhelming. But if on-line discussion is any indication, there's also a
good deal of dissatisfaction with that choice.
RSS Feed
The attacks on C++ come on two flanks. From the low-level side comes
People the argument that the language supports too high a level of abstraction,
and that we should go back to programming in straight C. This argument
holds that writing efficient code in C is easier than writing efficient code
in C++ because the level of information hiding afforded by C++ hides
inefficiencies from cursory perusal. For example, in C, you can read the
Search
line

a = b + c;

and know that a, b and c are primitive types and that the addition and the
assignment will generate, at most, a few lines of assembly code. In C++,
a, b and c could be objects of any size calling overloaded addition and
assignment operators that might generate still more temporary objects,
allocate memory, call sleep(), reformat your hard drive, etc. The only safe
way to prevent such shenanigans is to disable compiler support for C++
language features entirely.

The other camp of C++ criticism compares it to higher-level languages


and finds C++ wanting. This camp holds that C++ suffers under the
burden of backwards compatibility and slow ANSI/ISO standard
evolution. It lacks features found in more modern languages, such as
aspects, closures, garbage collection, reflection, and native support for
concurrency. The paleolithic C++ physical structure--.h include files
and .cpp implementation files--results in achingly slow build times and
forces programmers to write every function definition twice, once where
it's declared in the header and once where it's defined. We would be better
off, according to this argument, writing our games in C#, Eiffel or
Objective Caml.

Remarkably, the two sides don't even disagree. Instead, the sentiment is
commonly expressed that straight C is the way to go for core engine code
while less-performance-critical gameplay code should be written in a
high-level scripting language (for a cogent expression of this opinion, see
this post by Robert Blum in the SWEng-GameDev thread). C++ falls
awkwardly in the middle, a jack of all trades and master of none.

Given all this discontent... Why C++? Why has it been so successful, and
does the language deserve to see that success continue?

First, I'll get the meta-reason out of the way: Nothing succeeds like
success. The fact that C++ is the dominant language for game
development gives it a lot of inertia. If you want to hire experienced
programmers, it's much easier to recruit C++ gurus than it is to find
OCaml talent. If you're going to develop for consoles, Microsoft and Sony
provide C++ compilers, but for any other language you're on your own.
And if you want to link with middleware, most modern game middleware
packages--including Gamebryo, Havok, FMOD, SpeedTree and the
Unreal Engine--are written in C++. Developing in another language, even
C, is a lonely path.

The power of the C++ network effect is not to be underestimated. For


example, Naughty Dog used an in-house LISP variant called GOAL
(Game Oriented Assembly Lisp) for the Jak and Daxter titles. They had a
significant investment in GOAL, for which they'd written their own
compiler, linker and debugger. They supported dynamic reloading of code
by a running game and reportedly generated tight, efficient assembly.
After their acquisition by Sony, however, Naughty Dog were forced to
transition to C++ development. "Sony wants us to be able to share code
with other studios, and this works both ways - both other studios using our
code and vice versa," posted Naughty Dog lead programmer Scott
Shumaker.

But rather than dwelling on the advantages that derive from its existing
popularity, I'd like to focus on the inherent strengths of C++ for game
development. In doing that, it's important to understand how and why C++
evolved into the language it is today. C++ grew out of C. C was a systems
programming language that co-evolved with the Unix operating system
and that gained popularity as Unix spread. C was tight, close to the metal.
You can look at a C function and tell almost exactly what assembly will
result from compilation.
C++ adds layers of abstraction. C++ began as a set of extensions to C to
add support for the object-oriented concepts found in Simula, classes and
inheritance. As creator Bjarne Stroustrup writes in his C++ FAQ, "Since
1987 or so, the focus of development the C++ language and its associated
programming styles have been the use of templates, static polymorphism,
generic programming, and multiparadigm programming." C++ continues
to evolve to support new design paradigms.

The growth and evolution of C++ has been a mixed blessing. On the one
hand, C++ is truly a language for multi-paradigm development: the
language supports generic, imperative and object-oriented programming.
Any C++ program, or part of a C++ program, can be written in the
appropriate style to best model a particular problem domain. On the other
hand, C++ has been a victim of its own success. As new core language
and standard library features have been added to meet new needs,
programming in C++ has become a powerful but complicated business.
It's easy to hire people who call themselves C++ programmers, but
engineers who understand both the low-level details of the C++ object
model and the compile-time power of C++ template metaprogramming
are hard to come by. And C++, in the hands of an programmer without a
good grasp of the language, is a dangerous thing.

Despite this risk, I think that the answer is better education, not a
wholesale rush back to programming in C. Because in the right hands, C+
+ is a more powerful, safer, and--yes, really--more efficient language than
C is.

More powerful? Every C game I've seen has re-implemented virtual


function tables with structs stuffed full of function pointers. C++ has
native support for object-oriented code. The language's native syntax
allows expression that's closer to a programmer's intention. C++ template
metaprogramming is vastly more capable than macro coding with the C
preprocessor. And the C++ standard library offers a broad array of
containers and algorithms. You're likely to be able to implement any given
task with less code in C++, from low-level bit shuffling to high-level state
logic.

Safer? In C, if we write

#define MAX(A,B) ((A) > (B)) ? (A) : (B))

MAX(x++,2)

then x will be incremented twice after macro expansion. The inlined


templatized C++ std::max() function is equally efficient and free of such
unpleasant side-effects. The lack of templates in C encourages passing
structs through void pointers, as in the unfortunate standard library qsort()
function. This predilection for void* undercuts the protections of the type-
safety system and turns easily-caught compile-time errors into hard-to-
find runtime errors. In C, the Resource Acquisition Is Initialization idiom
doesn't exist. Scoped locks and smart pointers can't be implemented, so
leaks of memory and other resources become much more likely.

More efficient! The C++ standard's support of type-based alias analysis


allows C++ compilers to elide load and store instructions that compliant C
compilers cannot. (A full discussion of type-based alias analysis is beyond
the scope of this article, but see "Type-Based Alias Analysis" in Dr.
Dobb's Journal.) Inlining allows C++ compilers to generate programs that
make fewer function calls and therefore waste less time on function-call
overhead. In combination with templates, functors allow C++ to easily
generate efficient inlined custom code at compile time. This is why the C+
+ std::sort() will beat the perfomance of the C qsort() function every time.
Finally, the C++ standard library containers, though much-criticized by
developers, are likely to outperform equivalent code written by junior C
coders. (For that matter, STL containers have outperformed the custom
code they replaced in every case where I've seen data structures switched
to use the STL.)

While I prefer C++ to C, I do agree that a C++ engine core works best in
combination with gameplay code written in a language that supports a
higher level of abstraction. That's not because C++ lacks programming
constructs of more modern languages, though. I confess that I haven't
worked with aspects or closures enough to even know whether they give
great productivity improvements. I have done enough procedural
programming to doubt that code written in a procedural language is going
to be inherently more clean and elegant than code written in C++. And I'm
generally skeptical of the benefits of garbage collection. Memory is one
resource among many (file handles, critical section locks, D3D resource
reference counts, etc.), and a resource management paradigm that only
covers memory is of limited use. (If you think garbage collection "just
works," read this explanation of the complexities inherent in C#
finalization.)

No, the compelling advantage that a more abstract language has over C++
is faster iteration time. The efficiency and power of C++ make it the best
language choice for core game engine technology, where runtime
efficiency is important and iteration time is not. For gameplay code,
however, those requirements are reversed. The ability to iterate quickly on
gameplay and get immediate feedback on design changes is paramount.
But gameplay logic executes infrequently compared to physics or graphics
routines, so highly-optimized native-code inner loops are less important.

For rapid iteration, you want a simple language that compiles quickly or
doesn't need to be compiled at all. You want to be able to make changes
and see their effect immediately in-game, without having to restart, or
even reload a level. You do not want the daunting features of C++ that
make experienced programmers pause to think and make novice
programmers write buggy code: pointers, a menagerie of different integer
and floating-point types, multiple string representations and manual
iteration over containers.

It's because of these considerations that Lua has become almost as popular
in the game industry as C++--at least among those game companies that
elect to use an off-the-shelf scripting language. Lua is lightweight,
dynamically typed and interpreted. It's garbage collected, but as long as all
your other resources are owned and managed by code and not script,
garbage collection works just fine and saves you the headache of dealing
with memory allocation.

So I hate to admit it, but I come down on the side of conventional


wisdom. Write your game engine in C++. Write your gameplay in Lua.
Those might not be the right answers for the next generation. I can
imagine a language with better support for concurrency stealing the
application domain from C++ sometime in the next decade. And C#/Mono
is nipping at Lua's heels as a game scripting language already. But for
now, I think the C++/Lua combination is as good as it gets.

Any opinions expressed herein are in no way representative of those of my employers.

Home

You might also like