C gives you access to the "restrict" keyword which can result in a measurable performance improvement on DSPs; it lacks templates that bloat your generated code; ditto for implicit copy constructors and other "helpful" compiler-generated bloat; finally, C99 designated initializers are pretty useful in practice.
You *can* emulate the efficiency of C in C++, provided you do not use any C++ feature. However, without templates, exceptions and the STL what's the point of using C++ in the first place? You simply get worse compilation times and lose C ABI compatibility in exchange for... namespaces? Pretty weak.
Edit: even worse C++ new/delete cannot take advantage of multiple heaps, unless you write your own allocator (good luck), and tend to fail horribly when called during an interrupt. Once you lose the ability to call "new Foo", then a whole range of C++ constructs become impossible. And since everything has to be a POD, then you can just use C and be done with it.
(Yes, this is not your run-of-the-mill, out-of-order, branch-predicting x86_64 environment that will swallow all kinds of inefficiencies without complaint.)
As Sean mentioned above, even though restrict isn't in the spec, all the decent compilers support it anyway, in some form. As you know, informing the compiler that two pointers won't alias can produce some great results, so there's a good incentive for the compilers to support that C99 feature in C++
(the main compilers used by PC and console game-devs are GCC, MSVC, Clang, and SN systems, which are all decent these days )
The PS3 and 360 CPU's are in-order, PowerPC variants, where excessive loads (caused by aliasing) can ruin performance with load-hit-store stalls - restrict can do wonders when that's occurring in tight loops... The PS3 also has the crazy Cell CPU, which doesn't even have access to RAM directly (it's basically got a massive, software-controlled L1 cache, with batch/async memcpy communication to RAM) -- to write code for it, you need all the regular systems programming features of either C or C++.
As Sean said, this is GameDev.net, and the topic is why C++ is widely used in professional game development. The fact is that it is widely used. I don't mean to resort to argument by popularity or authority, but seeing that there's hundreds of organizations full of ridiculously talented programming teams who are using it for these kinds of low-level, embedded, high-performance projects (and who are producing amazing products), chances are that there's some good reasons for it... Maybe when you're working in one of these teams you'll get a chance to gain a new perspective on the language
I've used it on academic research projects and large corporate projects as well... and these experiences were not the same as in the games industry. It's a very different language on every project, depending on who's leading the project, and which sub-set of the language you're using. It is pretty ridiculous and over-complicated, so every project does basically use a different sub-set of the features. Actually, even the C projects at those places were pretty horrible
Game-developers generally avoid exceptions and RTTI (the compilers for game consoles often have these features disabled by default, with a command line option to turn them on!!), and often avoid the parts of the STL that deal with memory allocation, because embedded hardware requires much more care in that area.
A few hardware generations ago, we avoided templates, because compiler support was terrible -- one in particular who shall not be named didn't do 'COMDAT folding', which meant that vector<int*> and vector<float*> resulted in identical/duplicated asm routines being included in the executable, instead of one of them being merged/stripped...
Since then though, templates are one of the best reasons to use C++. You seem to be suggesting that templates result in "bloat" that makes your program run slower (which might be true on the above mentioned compiler *cough* CodeWarrior *cough* if measuring L1 I$ pressure... or if your compiler doesn't know how to inline... or if you're using STL templates with your STL-implementation's debug features turned on) but the simple counter-example is C++'s std::sort vs C's qsort.
qsort uses a function-pointer to call the comparison function in the inner loop - on PPC, this results in endless and completely unavoidable branch misprediction penalties.
std::sort uses a tempalted functor to call the comparison function in the inner loop, which results in it being inlined at compile time, avoiding the need to branch to an address fetched from memory. The resulting code from the templated sort algorithm is much more optimal than the C function pointer alternative.
You don't seem to be aware of "placement new". Default new does two things -- gets memory via something like malloc and also calls the constructor (and delete does something like free and also calls the destructor). Many game engines avoid using the default new / delete altogether (and default malloc / free altogether too!). Instead you can write your own new, which uses memory fetched from anywhere (malloc, the stack, a mapped file, whatever) and then use placement new to call the constructor at that address. You can then call the destructor manually when freeing that allocation.
Many games that I've worked on actually make liberal use of stack/linear/mark-and-release allocators. C++ lets you marry it's object model with any kind of allocation scheme such as this, if you care to - so you're not just limited to POD when using alternative allocation schemes.
On that topic, many game console OS's don't even provide malloc / new out of the box. It's often up to you to implement these routines yourself, using the raw OS functions for allocating physical memory ranges, allocating virtual address ranges, choosing page sizes, and binding the physical and virtual allocations together.
Most game engines are also extremely careful with memory management, often banning the use of malloc/new altogether, and forcing you to choose from several alternatives (multiple heaps, temporary stacks, pools, rings, etc), which usually provide amazing debugging capabilities (in development builds).
e.g. Here's one of EA's stack allocators, married with the C++ object model: http://dice.se/wp-content/uploads/scopestacks_public.pdf
Back to the STL - as I mentioned, many game-devs avoid the parts that deal with memory allocation (especially if coming from the previous generation of hardware, where total memory was very tight), but even these parts should provide a 1:1 performance with equivalent C code. The catch is that you've got to be experienced enough to know what that C code is. If you're using a fixed-size POD array in C, and vector of non-POD types in C++ that you haven't pre-reserved memory for, then of course you're going to notice a difference because that's apples-to-oranges. This is simply down to the author being decent at C and not experienced enough to write equivalent C++ code.
There's also the rest of the STL that doesn't have anything to do with memory management - such as the algorithm part; It's still handy to have sorting, searching, set logic, etc available out of the box... though people don't really use C or C++ because of their great standard libraries They use them because they let you talk to OS's and hardware, and also to be at a level where you can still make a decent guess about what the resulting ASM will look like.
On that note, ASM is pretty much never used in game engines. If something is so performance-critical that you'd resort to lovingly hand crafting ASM, usually just using intrinsics from C/C++ is enough (and perhaps actually portable across CPU's). Intrinsics can actually be faster, because they're understood by the optimizing compiler, and thus can be glued into the surrounding high level code better.
Regarding C vs C++, C certainly has it's merits so I wouldn't dismiss it... But even if ditching the STL, RTTI and exceptions completely, you still get templates (which let me write code that's simpler/maintainable, and also faster -- but also let you shoot your foot off in terms of both of those facets...), RAII (which formalizes C's error handling practice and greatly simplifies error-handling code, formalizes C's memory lifetimes by allowing you to connect heap lifetimes to stack lifetimes, and enables many debugging techniques to boot -- I seriously can't emphasize how amazing RAII is), dynamic dispatch in the rare case that I need it (and if you do really need it, the asm generated by C++'s virtual is likely way better than the equivalent code written in C -- on the flipside it's tempting to overuse this feature), template metaprogramming (which can be the devil's work, creating unreadable code that explodes your compile time... but also results in amazingly simple binding systems for scripting languages, reflection, etc...), much better support for OOD (which is often overused badly, but is solid as a rock when used properly), much cleaner math code with operator overloading (which can still be compiled into amazing SIMD ASM), different access specifiers (public/private, to make class invariant's more explicit - shouldn't have to explain why private is a good thing(tm)), and almost everything in C99 too.
The downside in C++ is knowing when to restrain yourself from writing bad code, because the language makes it so easy...
I dont really understand the compile time argument. Surely you guys use a build system that only compiles the source units that change since last build iteration right?
If LTCG is enabled (e.g. in optimized builds), then unfortunately the linker stage can take 1 minute+, regardless of how much code has actually changed
Game studios usually have 3 build profiles - full debug, internal development (debugging features, but optimized compiling), and retail (no debugging features, fully optimized compiling and linking).
Game engines typically avoid "typical C++ bullshit" that you might find in academic code-bases.
Man... it always depresses me when you use that link, because to this day I still have no idea what's going on.
Should we make a new thread to discuss it? Mike Acton was being deliberately smug and esoteric when he wrote it, I think.