why c++ is the most widely used language for professional game development?

Started by
34 comments, last by jpetrie 9 years, 9 months ago

Cache-friendly C++ code? That's a good one.
C++ may be more cache-friendly than Java, but that's it. If you've ever done any high-performance DSP programming, it's C and assembly all the way. C++ compilers generate code that is simply too inefficient to compete (and that's *after* you disable exceptions, RTTI and ditch the STL.)

Writing cache-friendly code just requires that struct does what you think it will do, POD exists, and that you can use real hardware pointers (virtual address space) and allocations without a middleman adding extra indirection, and optionally the ability to use intrinsics.
What does C let you do in this arena that C++ doesn't?
Even C# gives you these abilities (at least: explicit data structure layouts and raw pointers / allocations), but the code becomes extremely verbose because it's not designed to do that kind of work by default.

I work as a game engine consultant, which half the time means optimization work, which usually means writing cache friendly code. The engines are all in C++, so that means writing cache-friendly C++ code... Yeah it may look like the kind of code a C programmer might write in C++, but it's still C++ tongue.png

Game engines typically avoid "typical C++ bullshit" that you might find in academic code-bases.

Even if the compiler followed the spec and (it doesn't) the generated code is simply... bad (to put it mildly.) The same vendor has a perfectly functional C compiler that produces excellent code for this platform - is their C++ compiler to blame, or is it that the C++ specification makes it very difficult to write a well-performing compiler?

How different were the C and C++ implementations? Is the problem that C++ gives you a lot more tools than C, which tempts people into writing bad code? Or were you compiling the exact same code with a C and a C++ compiler, using the same settings?
e.g. the gross verbosity of manually implementing 'virtual' in C, means that people really think twice (or 10 times) before using that construct, whereas in C++ it's only 7 letters away...

This is the argument used by Linus Torvalds - basically the Linux kernel must be C because C programmers are typically more hardcore than C++ programmers. It's not really relevant when you're in control over who you hire into your organization and how their work is reviewed / guided cool.png

Its insane compilation model leads to terrible build times, and completely breaks down in large codebases. A windows build of Qt5 takes >2 hours on a quad core system with a SSD. A comparable codebase in C# would take less than 10 minutes (my system manages ~100Kloc of C# per second, which would build the whole 10Mloc of Qt5 in 1.5 minutes.

That's indeed something that C and C++ suck at compared to modern languages... but 2 hours? Really? I've worked on 1M+ LOC C++ projects and never suffered that. IME, a full build of commercial console-game size project is about 5-10 minutes compilation, and a few minutes in linking if LTCG is enabled, per config / per platform. At my last job, for each commit to the VCS, a poor-man's non-distributed build server would build, run and test 3 platforms x 2 configurations in ~20 minutes.
10 minutes is still terrible in my opinion wink.png but if you're on a 2h project, I'd subtly recommend this to the project lead.

Advertisement


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.


hat's indeed something that C and C++ suck at compared to modern languages... but 2 hours? Really? I've worked on 1M+ LOC C++ projects and never suffered that. IME, a full build of commercial console-game size project is about 5-10 minutes compilation, and a few minutes in linking if LTCG is enabled, per config / per platform. At my last job, for each commit to the VCS, a poor-man's non-distributed build server would build, run and test 3 platforms x 2 configurations in ~20 minutes.

It took me probably longer than 2 hours to compile the Linux kernel. At work we use a distributed build system, but even then compiling the codebase takes about 10 minuets (and I suspect that would grow to ~2 hours on a single machine, and we generally follow most common compile-optimization practices (like forward-declaring instead of including in header files when you can).

Cache-friendly C++ code? That's a good one.
C++ may be more cache-friendly than Java, but that's it. If you've ever done any high-performance DSP programming, it's C and assembly all the way. C++ compilers generate code that is simply too inefficient to compete (and that's *after* you disable exceptions, RTTI and ditch the STL.)

Writing cache-friendly code just requires that struct does what you think it will do, POD exists, and that you can use real hardware pointers (virtual address space) and allocations without a middleman adding extra indirection, and optionally the ability to use intrinsics.
What does C let you do in this arena that C++ doesn't?

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.)


Even if the compiler followed the spec and (it doesn't) the generated code is simply... bad (to put it mildly.) The same vendor has a perfectly functional C compiler that produces excellent code for this platform - is their C++ compiler to blame, or is it that the C++ specification makes it very difficult to write a well-performing compiler?

How different were the C and C++ implementations? Is the problem that C++ gives you a lot more tools than C, which tempts people into writing bad code? Or were you compiling the exact same code with a C and a C++ compiler, using the same settings?
e.g. the gross verbosity of manually implementing 'virtual' in C, means that people really think twice (or 10 times) before using that construct, whereas in C++ it's only 7 letters away...

They were functionally identical, but the C++ used a couple of STL constructs whereas the C version used hand-rolled implementations. Result: the C++ code could no longer fit into the L2 alongside the SYS/BIOS6 kernel, resulting in a dramatic performance drop. No virtual inheritance, exceptions or anything fancy - just good old std::vector and std::list.

Yes, I could rewrite the C++ code to avoid the STL - but then there's simply no point in using C++ in the first place.


Its insane compilation model leads to terrible build times, and completely breaks down in large codebases. A windows build of Qt5 takes >2 hours on a quad core system with a SSD. A comparable codebase in C# would take less than 10 minutes (my system manages ~100Kloc of C# per second, which would build the whole 10Mloc of Qt5 in 1.5 minutes.

That's indeed something that C and C++ suck at compared to modern languages... but 2 hours? Really? I've worked on 1M+ LOC C++ projects and never suffered that. IME, a full build of commercial console-game size project is about 5-10 minutes compilation, and a few minutes in linking if LTCG is enabled, per config / per platform. At my last job, for each commit to the VCS, a poor-man's non-distributed build server would build, run and test 3 platforms x 2 configurations in ~20 minutes.
10 minutes is still terrible in my opinion wink.png but if you're on a 2h project, I'd subtly recommend this to the project lead.

Have you *ever* tried to compile Qt? If not, try that once - it's an interesting experience. smile.png Its copy of WebKit alone takes the better part of an hour to compile.

A full rebuild of our dependency tree takes slightly less than 4 hours on a i7 with 16GB ram and a SSD. (This includes Qt5, VTK, ITK, DCMTK, OpenCV, Coin3d and half a dozen other libraries. Times are slightly better on linux/gcc and quite a bit better on mac/clang.)

Btw, 1M LOC of C# compile in roughly 10 seconds on my system. 10 *seconds*. How does that sound for a productivity boost? ;)

[OpenTK: C# OpenGL 4.4, OpenGL ES 3.0 and OpenAL 1.1. Now with Linux/KMS support!]

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.

Most of the relative "slowness" of C++ compilation in comparison to C is because of templates. I see no reason why a C++ compiler would be slower than a C compiler (which is already pretty slow anyway) when you're not using them.

For that matter, template bloat is mostly a solved problem, Unless you're working on an obscure compiler, you're going to have reasonable template expansion. However, a crap compiler is not a language problem (except loosely correlated with language complexity).


Btw, 1M LOC of C# compile in roughly 10 seconds on my system. 10 *seconds*. How does that sound for a productivity boost? ;)

1M LOC of C# compiles in 10 seconds because it's not compiling. At least not to native code. It's compiling to MSIL and amortizing the rest of that at runtime with a jitter. That's a lot faster because it's fundamentally a different process, and you're not comparing apples to apples. C# native is supposedly a thing now (or at least will be), so you should try that for a better comparison.

This funny but truthful image shows the crux of the matter: http://global3.memecdn.com/If-programming-languages-were-tools_o_32267.jpg


Funny, but the PHP tool is wrong. We all know what it would really be:

http://blog.codinghorror.com/the-php-singularity/

Sean Middleditch – Game Systems Engineer – Join my team!

As a foreword to my responses to Fiddler: this is Gamedev.net, not ProprietaryEmbeddedDSP.net, so you're going to be arguing with folks who work on a very different set of problems and domains than many of your arguments seem to be stemming from.

... and normally I know better than to argue dogmatic topics like programming languages on the Internet but today is my let's-get-nerd-sniped day apparently. smile.png

No virtual inheritance, exceptions or anything fancy - just good old std::vector and std::list.


So iterator debugging was disabled? IOStreams was not linked in? Exceptions were disabled (they require a lot of additional generated code/tables to support) ?

We typically use a custom replacement for std::vector (and other containers) that uses raw pointers for iterators, doesn't use exceptions, has no out-of-bounds checks, makes proper optimizations for trivially copyable/destructible/movable types, uses a simpler allocator model, etc. Compile with -fno-exceptions (or the equivalent for your compiler) and it generates quite efficient code. There's still plenty of value in a reusable type-safe contiguously-allocated container, of course, even without all that other crap that the STL gives you.

If that's not good enough, see the BitSquid Foundation Library for a very C-like approach to offering type-safe containers utilizing C++ templates while minimizing compile times and appealing to other C coder sensibilities.

There are also small_vector or stack_vector classes around that avoid (or disallow) heap allocation, dyn_array which emulates C's alloca-based arrays, and so on, all of which have performance advantages that won't be present in std::vector or even most C code in my experience.

Yes, I could rewrite the C++ code to avoid the STL - but then there's simply no point in using C++ in the first place.


The STL is hardly the best reason to use C++. smile.png

C gives you access to the "restrict" keyword which can result in a measurable performance improvement


While not (yet) standard, I don't know of any game-relevant C++ compiler that doesn't support restrict (sometimes spelled __restrict).

ditto for implicit copy constructors and other "helpful" compiler-generated bloat


It's regrettable that they're there normally, but we have =delete now to deal with that (and other problems). I habitually use =delete (or inherit from a non_copyable "trait" type) for the copy constructor and assignment operator and declare all non-trivial (in the C++11 definition of "trivial") methods in .cpp files to needless code generation or linking overhead (and rely on LTO to inline things where and when appropriate in release builds).

That doesn't fly if you're not on a reasonable up-to-date compiler, admittedly.

C99 designated initializers are pretty useful in practice.


I'd expect to see something like them in C++17, given the noise I'm seeing on the ISO forums. They may even just use the designated initializer syntax since compatibility is a popular thing with the C++ committee. There's some conflation of this with generalized named-argument support, which has a lot of additional problems to solve of course, but there seems to be plenty of momentum behind it.

Most of the relative "slowness" of C++ compilation in comparison to C is because of templates. I see no reason why a C++ compiler would be slower than a C compiler (which is already pretty slow anyway) when you're not using them.


Don't forget exceptions. A C++ compiler has to generate a lot of extra unwinding code/tables to deal with the possibility of an exception being thrown. If there is any one feature of C++ I'd claim as being a massive mistake that makes C++ a worse language than C, it's exceptions. Thankfully, -fno-exceptions (and equivalents for other compilers) is a thing.

The C++ headers are often quite bloated, too. Including a "simple" header like <memory> can have a huge impact (which is the primary reason I prefer a custom replacement for unique_ptr that has no header dependencies).

For that matter, template bloat is mostly a solved problem, Unless you're working on an obscure compiler, you're going to have reasonable template expansion. However, a crap compiler is not a language problem (except loosely correlated with language complexity).


On a single file, sure. That horrific translation-unit model of compilation that C++ uses (inherited from C, of course!) means that you have to re-expand the template for each translation unit. And then the linker has to do a ton more work to merge all the duplicate expansions, making link time far worse.

Modules in C++ (proposed, maybe available by C++17) would remove a lot of these problems. Unity/blob builds are a decent interim solution that helps a lot.

Also remember that a lot of game developers _do_ work with either old compilers. Lots of us are stuck on ancient Visual C++ releases, GCC 4.2 forks, etc. And of course many game devs do have to use obscure compilers for various reasons. The advice we can give new coders wanting to start new projects (where we can assume modern mainstream idealized tools) is not quite the same advice we can give AAA developers working in the trenches. smile.png

-- general response to much of this thread --

Nobody needs the fastest possible code ever; they just need "fast enough" for the given situation and the time and money to achieve it. Performance fetishism is a weakness - even in a game programmer - and just another example of "perfect is the enemy of good."

Sean Middleditch – Game Systems Engineer – Join my team!

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? So if I make a modification to a very large C++ project, it really does only take ~5 seconds to complete. Most of that time is the Makefile output overhead scrolling down my terminal.

Not to mention the compile time of most projects are often dwarfed by the time required to build an output APK or IPA package for mobile devices. And I know Unity is a little bit different to a pure C# platform but compiling a web package for that is bloomin time consuming. We have recently used Mutiny 3D (my C++ Unity engine clone) at work and the build / debug iteration times are much quicker even though the behaviours are written in C++.
http://tinyurl.com/shewonyay - Thanks so much for those who voted on my GF's Competition Cosplay Entry for Cosplayzine. She won! I owe you all beers :)

Mutiny - Open-source C++ Unity re-implementation.
Defile of Eden 2 - FreeBSD and OpenBSD binaries of our latest game.

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++ wink.png

(the main compilers used by PC and console game-devs are GCC, MSVC, Clang, and SN systems, which are all decent these days happy.png)

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 cool.png
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 laugh.png

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 wink.png 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... sad.png

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 sad.png
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.

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? So if I make a modification to a very large C++ project, it really does only take ~5 seconds to complete. Most of that time is the Makefile output overhead scrolling down my terminal.


Of course. Even with such systems, it's not uncommon for large projects to take 20+ minutes (or even hours) for an incremental non-optimized build after making trivial changes.

This usually happens on projects with bad practices (including too many headers rather than using forward declarations, no dedicated build engineer, etc.), and is a problem on C as well but is generally far worse on C++.

I'll say it again: your experiences on what I assume are small open source or hobby projects don't really scale up for those of us working with projects with many millions of lines of code (like many big AAA games/engines).

Even your Makefile time is bad. Consider the Chromium folks who created a whole new build tool (ninja) just to avoid the massive time that make spent doing its job checking the huge number of files that comprise Chromium and its internal libraries. Really big code is bigger than you maybe think it is. smile.png

Sean Middleditch – Game Systems Engineer – Join my team!


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.)

I don' t want to be argumentative, but as others have pointed out, this passage and others seem to point out two things -- firstly that you're basing your views on a very specific environment, which is fine, but not one which is shared by most people here -- Embedded systems and DSPs have always been a different world, outside of maybe GPU compute, any game console of the last 10 years looks reasonably close to a PC, even handhelds. Secondly, it points out that your understanding of C++ seems to be a little skewed / outdated, or that your experience in the embedded/DSP landscape intersects with your own priorities in ways that aren't of concern to most of the rest of us.

On the topic of templates, for instance, you keep referring to bloat -- but templates don't lead to executable code that you aren't using, the linker is perfectly capable of eliding unused member functions of a template class that gets instantiated, and perfectly capable of de-duplicating code generated from template instances that happens to be identical.

On the case of exceptions, I tend not to find them being a problem for me personally. I acknowledge that they do have a fairly high cost, that this cost tends to be inappropriate for high-performance code, and that the default state of affairs have many people paying this cost without realizing or benefiting from it (And I also have relatively little sympathy for those who lack an understanding of their tools that leads to this situation).

But what I think we're seeing here is a kind of cultural difference between people who prefer C and those who prefer C++. C users tend to prefer that the compiler do as little as possible behind their backs, and for that greater degree of certainty are willing to pay the cost of having to write more code explicitly. C++ users tend to prefer to burn that candle from the other end, we trust the compiler to automate a reasonable amount of grunt-work for us, and are willing to pay the cost writing our code in a way that helps the compiler understand our needs more clearly so that it can do its best job. In real terms, a C programmer is happy to write two parallel sets of functions and data structures where a C++ programmer would just as well write a template. Regardless of how we burn this candle, both camps burn effort to move toward the middle, and the approach you take ultimately depends on which is more comfortable and convenient for you, working in the environment you work in. To my mind, either approach is perfectly valid, subject to your own constraints.

We can all agree that C++ is flawed in certain ways, some of them arguably significant. C is 'flawed' too, in the way that it almost dogmatically does less than it could, and perhaps should (by which I mean, for example, that C could easily support templates and doing so has no inherent performance cost). We can agree that C and C++ are different, and we can place a lesser or greater significance on those differences, but they really cannot be used as arguments about why one or the other language is superior.

throw table_exception("(? ???)? ? ???");

This topic is closed to new replies.

Advertisement