Alexander Neundorf found yet another flawed, inaccurate C/C++ comparo. I’d add comments to the blog entry, but I don’t feel like looking up my user name, and this also satisfies my own blog quota for the week. =D
The article makes a few assertions about the perfomance of C++ code compared to C. Let’s debunk them:
- “C++’s virtues are expensive. Advanced OOP features, such as templates and the practice of using classes in the place of primitives, to name two examples, cause unacceptable code bloat.”
Well, just as in other languages, C++ has features that may be counterproductive in some situations. And as always, the solution is to **don't use them**. Templates, by the way, are **not** object-oriented. Instead they are a form of generic programming. You are perfectly free to do C and Java-style collections if you'd like by holding pointers to everything, where at least you can get C++ type safety.
As far as using classes instead of primitive types go, if you're really only able to use primitive types, then just use primitive types. You'll still gain C++'s improved type safety abilities.
- “A C++ compiler may generate many routines for one function (templates) or create routines where no function explicity appeared (constructors, casts, etc.)”
You've already seen my response to templates. People should keep in mind that templates are simply a better form of C macros. In some cases it may actually reduce bloat. Think about it: Say you have a moderately complex macro to retrieve a value. It's a macro because you can't use a function (more than one type), and it generates a non-trivial amount of code (perhaps it has to lock a mutex).
In this case, a template would actually **save code**, because it would remove all of those inline macro expansions (which lead to serious code bloat), and instead replace them with a function call (only one function per type). This is especially useful on systems with small processor caches, such as embedded systems.
“hidden functions” is another non-argument. The functions are hidden because you always have to use them. `FILE *` structures don't automatically appear, do they? No, you have to call `fopen()`, `fdreopen()`, etc. And it's likewise with C++. Instead of forcing you to remember which exact function you have to call, you can instead use constructors. These are functions that you would have to call in C anyways, so I don't see how we can call this anything other than a win for C++, not a loss.
- “Virtual methods and polymorphism complicate runtime linking and require many relocations. This slows C++ application launch time considerably.”
Now this can certainly be true (although templates and polymorphism are the big killers here, not necessarily virtual methods). However, we don't live in 1999 anymore. Linkers and compilers have improved, so that they don't generate a billion function names when the C++ code only needed 10 (e.g. the visibility support in recent GCC), and we now have programs available to “prelink” binaries so that they load quickly even if they have a lot of symbols. I'll admit this has been an issue, but it's not such a big deal in 2005.
- “Each class with virtual methods has an associated vtable array, which adds memory overhead.”
Well duh, but it's not like it adds 10K per class. In fact it's actually more efficient than what GTK+ does to support virtuals (oh, by the way, [GTK+ has virtual methods too](http://developer.gnome.org/doc/tutorials/gnome-libs/gtk.html#AEN442)), since it can be done at the language level instead of being emulated in C.
- “C++’s tighter type-checking makes it difficult to write the space-conscious code reuse common to C applications (think:
void *
).”
And people seriously wonder why it is that in 2005 we still have buffer overflows. As Alexander pointed out, C++ didn't take away `void *`. You can still use `static_cast` (and even C style casts) to your heart's content. Sure, C++ will actually put up a fight when you're doing bone-headed things and throwing pointers around willy-nilly. But that's supposed to be a good thing, right? Oh, wait, it's **embedded**, we don't need to worry about security problems there. :-P
- “The small, simple code demanded of embedded projects provides maintainability. There is no reason to assume OOP will further simplify such systems.”
BZZZT, WONG!! A clean design provides maintainability, not the latest ooh-look-how-many-unintended-sideeffects-I-can-use mentality. Of course a clean design is commonly a small design, but there's a design nonetheless. Luckily, C++ is more than just OOP, and supports many different types of design. If you're trying to scrap OOP though, you'd better look for something other than GTK+, which also [uses a heavily object-oriented system](http://developer.gnome.org/arch/gtk/object.html). _“Although GTK+ is written in C, a language without explicit support for object-oriented program, the design of GTK+ is heavily object oriented.”_
- “GUIs may not have a simple solution in a rigorous OOP model.”
Well, it's a good thing you're using GTK+, which isn't heavily object-oriented, huh? Oh, wait…
- “It’s easy to get carried away and start doing OOP for OOP’s sake. The One True Object Model may describe a problem perfectly, but it comes at the cost of excessive code.”
See above. And above that.
- “Carefully written C code can be much faster than C++ code, especially on embedded hardware. GTK+’s hand-crafted object system offers much better spatial locality than C++’s more numerous and distributed constructors. Our device has a tiny cache, so locality is an especially important performance consideration.”
To be honest, I really don't know. In the end, locality is up to the linker and compiler, not the programmer unless he's using special features to control where .o files get placed in the final result. Of course, such features would work with both C and C++. And, once again, I've already pointed out that any constructors you'd need for C++ objects you'd also need for C structs. I suspect there isn't much difference, even on those oh-so-fragile little embedded devices.
I don’t know why people always assume that you’re forced to use objects everywhere with C++. I mean, sure C++ makes it ridiculously easy to use a safe string type instead of always working with const char *
. But no one’s forcing you. Even if you do nothing more than use C++ as a stricter C it’d still be a win for you. Although if you actually investigated you’d find that there is no difference between an object with no virtual methods, and the eqivalent C representation of a struct and related functions. Except that the syntax would be much cleaner.
I just wish that people would have the cojones to say what they mean sometimes. Like I wish the author of the piece would have just said: “Look, I don’t like C++, don’t feel like learning it or picking it up, I just want to code in C, and that’s that.” instead of rambling on and spouting half truths and other FUD about C++.
There *are* things to fault about C++, easy things too, and yet every point he brought up wasn’t one of them. Whatever. :-/