C versus C++
I know that this is a sensitive subject that has been beaten to death already. Still, I’d like to share my opinion on this. Let me open with a quote by Bjarne Stroustrup about comparing programming languages which can be found in his FAQ:
“Language comparisons are rarely meaningful and even less often fair. A good comparison of major programming languages requires more effort than most people are willing to spend, experience in a wide range of application areas, a rigid maintenance of a detached and impartial point of view, and a sense of fairness.” — Bjarne Stroustrup
Well put. But C++ is supposed to be an improvement over C in that it allows the same style of programming you’re used to in C and makes other mechanisms available that are intended to make a programmer’s life a lot easier. So, it makes sense to discuss whether C++ has actually achieved what it was designed for. In his own words Stroustrup answers the C-versus-C++ question this way:
“C++ is a direct descendant of C that retains almost all of C as a subset. C++ provides stronger type checking than C and directly supports a wider range of programming styles than C. C++ is “a better C” in the sense that it supports the styles of programming done using C with better type checking and more notational support (without loss of efficiency). In the same sense, ANSI C is a better C than K&R C. In addition, C++ supports data abstraction, object-oriented programming, and generic programming [...]
[...] I have never seen a program that could be expressed better in C than in C++ (and I don’t think such a program could exist – every construct in C has an obvious C++ equivalent). However, there still exist a few environments where the support for C++ is so weak that there is an advantage to using C instead.” — Bjarne Stroustrup
I basically felt compelled to comment on this subject because a friend of mine pointed me to some mailing list entries (git mailing list) of Linus Torvalds. Let’s see what Torvalds has to say about C++:
“C++ is a horrible language. It’s made more horrible by the fact that a lot of substandard programmers use it, to a point where it’s much much easier to generate total and utter crap with it. Quite frankly, even if the choice of C were to do *nothing* but to keep C++ programmers out, that in itself would be a huge reason to use C. [...] I’ve come to the conclusion that any programmer that would prefer the project to be in C++ over C is likely a programmer that I really *would* prefer to piss off, so that he doesn’t come and screw up any project I’m involved with.” — Linus Torvalds
He claims that the share of unqualified C++ programmers is higher than the share of unqualified C programmers and that this has something to do with the design of C++. This is how I read it. I can’t confirm nor deny this. If you believe this to be true and need to rely on other programmers’ help this would be one argument among others you should consider when you need to decide between C and C++. Just for the record: A qualified C++ programmer knowns about what’s going on except maybe in case of some library with heavy template magic in it. He knows about it and appreciates the fact that he doesn’t need to write verbose and possibly error-prone application code. Torvalds continues:
“C++ leads to really really bad design choices. You invariably start using the “nice” library features of the language like STL and Boost and other total and utter crap, that may “help” you but causes (1) infinite amounts of pain when they don’t work (and anybody who tells me that STL and especially Boost are stable and portable is just so full of BS that it’s not even funny) …” — Linus Torvalds
Granted, the complexity of C++ makes writing standard conforming compilers difficult. The fact that Boost libraries contain compiler-specific workarounds is bugging me. The style of programming you find in the STL and Boost (read: the compile-time polymorphism kind of generic programming) is still rather new. So, it naturally comes with pros (reusability & efficiency) as well as cons (bad error messages). But nobody is forcing a certain programming style on you. You can still follow your C-style way of doing things and sprinkle it with a couple of C++ conveniences here and there that make your program less verbose and less error-prone. But I’m sure you’ll quickly notice that the STL is actually doing you good. Why should you reinvent the wheel all the time or resort to type-unsafe trickery when the STL can help you out easily? Torvalds’ second bullet point is:
“… (2) inefficient abstracted programming models where two years down the road you notice that some abstraction wasn’t very efficient, but now all your code depends on all the nice object models around it, and you cannot fix it without rewriting your app.” — Linus Torvalds
Inefficient abstracted programming models? Well, if you need a certain C++ feature you make use of it. If you don’t, then don’t. I rather prefer using the C++ way of doing OO with polymorphism than resorting to verbose and error-prone “OO emulation” in C in case I need OO with dynamic polymorphism etc. Whether you need this or don’t is also a matter of your design. You have to face this design decision in both worlds. I personally don’t do big class hierachies and virtual functions because mostly I don’t need this for my kind of applications. Anyhow, efficiency is a major goal of C++ and believe it or not: It is efficient. Don’t blame C++ when your program performs poorly. You just don’t know what you’re doing. Every language has its share of unqualified programmers.
“In other words, the only way to do good, efficient, and system-level and portable C++ ends up to limit yourself to all the things that are basically available in C. And limiting your project to C means that people don’t screw that up, and also means that you get a lot of programmers that do actually understand low-level issues and don’t screw things up with any idiotic “object model” crap.” — Linus Torvalds
I beg to differ. It’s a matter of your programming style. You don’t need to limit yourself to the C subset to produce “good, efficient and system-level and portable C++” code. In fact, I consider the probability of screwing up in C to be higher than in C++. To just give you an example: The lack of the RAII idiom in C just asks for the presence of resource leaks. Let me give a short summary of some of the features C++ adds to C:
- OO paradigm (class hierachies, polymorphism). If you need this, you’re better off with C++. Avoid emulating this in C. You can’t really do anything about one or two more levels of indirection when dynamic polymorphism is what you want.
- “simple” classes (= deluxe version of C’s ADT-style programming). It comes with the powerful RAII idiom which is a big plus in terms of resource management. It helps you avoid resource leaks and is a very convenient feature. No efficiency problem there. You don’t have RAII in C, unfortunately.
- generic programming is a powerful technique. It can increase code reuse without abstraction costs. Still, it’s a rather new programming style and kind of a pain in the a** when you made a programming error. Fortunately, the new C++ version will have a much better support for this programming style.
- Things like the STL containers and algorithms are prime examples of the previous two bullet points. They make your life a lot easier without abstraction penalties in terms of memory space and runtime efficiency. If you want to do something similar in C you’d have to resort to type-unsafe casts and macro trickery that certainly doesn’t look less convoluted nor is easier to use than their type-safe and more powerful C++ counterparts.
The above list is not exhaustive. For example I didn’t mention the exception mechanism. Torvalds’ conclusion is:
“So I’m sorry, but for something like git, where efficiency was a primary objective, the “advantages” of C++ is just a huge mistake.” — Linus Torvalds
I’m sorry, but apart from the share-of-unqualified-programmers argument which I can’t confirm nor deny he didn’t mention any actual disadvantage of C++. This efficiency argument he brought up is moot. The use of dynamic polymorphism is a design decision. Emulating this in C is at least as costly as using native C++ features. The STL kind of programming can even outperform C (power of templates and function inlining — compare C’s qsort with C++ STL’s sort). I was surprised that Torvalds didn’t mention C++ ABI incompatibilities between different compilers and even compiler versions as a disadvantage. This is actually a real problem. Name mangling and the implementation of exceptions are some of the things compilers might handle differently. So, if you plan to write a library in C++ this should also be considered. You see, I do acknowledge problems with C++. But obviously I’m one of those guys who think that C++ is a good idea. For me the advantages outweigh the disadvanages. I think that many people who bash C++ just apply a different weighting to the pros and cons and/or don’t qualify as someone who has “a detached and impartial point of view”.
There. And I didn’t even insult anybody, did I? :-)