Welcome to this round gents and gals, it’s time for one of the big boys. C++ is probably best described as the grand-daddy of many modern, object oriented programming languages. Basically, it has been wielding influence all over the place and it is undeniably one of the most popular languages in existence that clearly deserves its place – or does it? Especially among newbies, C++ is commonly being hyped up to heaven – that is, until they fall flat on their faces and fracture their noses for being too cheeky. In the shadow of its popularity lie numerous flaws and caveats that will get even the most experience programmers hurt sooner or later. Frankly, it sucks – though the reasons why might not be entirely obvious.

¿What’s your problem with El Señor?

To be honest, I don’t really have a problem with that language; I just don’t think it’s a particularly good one. Actually, it does suck quite a bit. Of course I do acknowledge that it has lots of features, that it lets you code the way you want to and that there is a compiler available for basically any system. That’s awesome, comes in extremely handy for the plethora of different situations we’ve to deal with and is probably the very reason why C++ is so popular and powerful. However, all of that only makes it a capable language, it doesn’t make it a good language – and here’s why.

Relics from the Past

C/C++In my opinion, C++ is this weird Frankenstein velociraptor that somehow survived the dark ages of programming and is now constantly being revived and patched up. The members of the standardization committee are trying hard to make things a little better by applying tons of makeup over its wrinkles. Obviously, this doesn’t work out too well since it’s still the same ugly beast under the mask. The problem here is that C++ is old – and I mean the antique kind of old that deserves to be put into retirement.

The project was first called “C with Classes” and later renamed to C++ in 1983. As its name now joyfully indicates via the postfix increment operator, it is supposed to be one step ahead of C (technically, by incrementing C and returning the old value. ++C would be correct, though that one looks dumb. Wink).

While the general concepts of object oriented programming that C++ derived from Simula (and not Smalltalk, contrary to popular belief) were already established, C++ combined the advantages of abstractions with the flexibility and performance required for low-level system programming.

Back in 1983, the programming environment looked entirely different – though this world has long changed. The circumstances aren’t nearly as bad anymore, yet the core of the language has been left untouched.

Relation between C & C++

There is a strong and obvious connection between the two, with C++ heavily extending the feature set of C. However, keep in mind that strictly speaking, C++ is not a superset of C, which is a rather common misconception. Although it is true that most (well-written) C programs will compile successfully under C++, there are certain constructs that are valid in C which will either produce a compile-time error in C++ or execute differently at runtime. The classic example would be memory allocation that requires an explicit cast in C++:

I do not work often with strict C compilers or even procedural C++ code, which is why I why I keep the C related part short. Many of the arguments here count for both C and C++, mostly due to their close bond with each other. I do think, however, that C is a much cleaner language, allowing you to maximize your code’s compatibility and portability without slaughtering readability too much (then again, you can write FORTRAN in any language).

I wanted to point out here as a side note that Linus Torvalds made his infamous strong opinions on C++ clear once again in this pretty interesting, though not so political correct thread (not that anyone expects otherwise from him), stating:

C++ is a horrible language. It’s made more horrible by the fact that a lot of substandard programmers use it, to the point where it’s much much easier to generate total and utter crap with it. Quite frankly, even if the choice of C [for the Git project] were to do *nothing* but keep the C++ programmers out, that in itself would be a huge reason to use C1.

– Linus Torvalds

I do not necessary agree completely with his statement, but one thing is just spot on: due to the high complexity of C++, it is definitely possible to “generate total and utter crap with it”. Those who have worked with C++ probably know that it is rather challenging to keep large projects well-structured and maintain a high level of readability.

Legacy Code & Compatibility

The de facto compatibility with C and its own backwards compatibility are both its blessing and curse. Bjarne Stroustrup put it nicely when he said, that the problem with C++ is that it cannot be cleaned up due to the tremendous amount of decade old legacy code that is still being used productively by businesses all over the world2.

Generally, backwards compatibility is regarded as a positive trait of any language, which is definitely true. However, the unfortunate side effect is that the language is getting cluttered up with new features over the years that somehow need to work together with all this unnecessary and totally outdated stuff from the last millennium. Things like the primitive include system and the naïve preprocessor could be replaced by much more efficient and practical mechanisms. Doing so without breaking backwards compatibility is impossible, which is exactly why it will never happen.

Parts I Really Dislike

First I thought I had a lot to say about C++. Well, it turned out that this is actually not the case. I tried to come up with numerous bad things to mention here and made several notes over the past few weeks. Even though I could think of quite a few horrible parts, I had to hold back and reflect on each of them. I realized that all of these “features” suck for a very good reason – complaining or even ranting about them wouldn’t be justified. Unlike other languages (looking at you, PHP) that just have been badly designed from the start, C++ is designed rather well given the circumstances, its purpose and its compatibility constraints. C++ is being developed and extended with great effort to make it as good as possible, while still keeping its legacy relics intact and putting all power into the hands of the developers to deliver a truly general purpose programming language.

Include System & Preprocessor

C++ does not have a proper module system that most modern languages provide. D, Java, C#, Python, Clojure, you name it. All of them got one. In combination with its primitive preprocessor, this usually results in a messy structure of header files and implementation files that rely on include guards to give basic protection against multiple inclusion.

God forbid if you have to deal with macro definitions that are scattered all around the source tree which likely cause unintended results after the macro expansion took place. Even small things like missing parenthesis around macro arguments or parameter specifications with additional operations can very quickly result in errors that may be difficult to track down:

Macros generally don’t behave like one would expect them to. The usual approach is to avoid macro definitions whenever possible and simply replace them with regular functions. Apart from other goodies like type-safety and better error handling, such functions will normally be inlined automatically by the compiler anyway.

Another downside I noticed is that the include system and the preprocessor give IDEs a hard time to figure out what belongs where and often cause them to deliver false results (auto-completion, navigation, code analysis, etc.). Kudos to the IDE developers though, I have noticed some major improvements during the last couple of years when it comes to the ability to effectively parse complex C++ macro definitions.

Overall though, having to rely on this system is just a mess and I wished there was a good alternative…

Undefined Behavior

What’s really unfortunate is that “undefined behavior” is part of the language and its specifications. Initially, some aspects were left undefined in order to be able to efficiently deal with different hardware and to avoid unnecessary overhead due to over-specification.

Do note that programmers often confuse the terms “implementation-defined” with “undefined behavior”. Parts of the language that are “implementation-defined” still allow the developers to write perfectly specified code as long as the target machine is known3.

Again, as it is with all the other bad parts, this will probably never be changed – it can’t be changed. Even Bjarne Stroustrup agrees in an interview over at MSDN that way too many things have been left undefined or implementation-defined. If C++ was redesigned from scratch, there would likely be no undefined behavior at all.

However, I don’t have a time machine and we just cannot break hundreds of millions of lines of code by picking a set of resolutions today4.

– Bjarne Stroustrup

Some of the semantic elements that have been left undefined involve even simple concepts like the execution order of function calls:

It is not defined, whether foo() will be called before or after  bar() has returned. That’s just silly.

Operations, such as division by zero, integer overflows or out-of-bound memory access will also result in undefined behavior. Granted, these things should not occur and can generally be avoided if the code offers even a slight hint of quality. However it would still be nice to have a well-defined behavior here, especially when talking cross-compiler and cross-platform.

Language Complexity

As a multi-paradigm system programming language, C++ is a complete beast when it comes to its feature-set and its specs, followed up with a steep learning curve and a very long path to mastery. It’s challenging to keep track of all its complex syntactical constructs that more often than not seem confusing and ambiguous.

Is it too complex? I don’t think so; there are thousands of programmers that speak C++ as if it was their mother-tongue. Its difficulty is clearly bearable, though I’d imagine that it is unnecessarily more difficult than it needs to be.

Within C++, there is a much smaller and cleaner language struggling to get out. […] And no, that smaller and cleaner language is not Java or C#

– Bjarne Stroustrup

Well, obviously it’s not Java or C#. These languages could never fulfill the demanding requirements of low-level hardware programming. Supporting even a fraction of C++’ native features would mean to extend their functionality considerably, converting them into an equal mess with similar problems.

However, it’s interesting to see some modern high-level features (e.g. lambda expressions, pure functions, …) being added to C++. I warmly welcome these changes, even though they do – again – add more complexity. I’m still waiting for that integrated garbage collector though that has been mentioned by Bjarne Stroustrup in 2000 in an interview with Slashdot. Crazy

So, what smaller and cleaner language could that be? What would it look like? The D Programming Language comes pretty close to what I’d expect from a modern language that shares its goals with C++. I briefly had the pleasure to take a look at D and I was amazed by its elegance and simplicity. I do not have enough experience to judge D, though I highly recommend checking it out.

Even though I agree that there is a concise language hidden in C++, whatever it might look like, I still strongly believe that it does not matter. This language will probably never see the daylight. C++ can’t be pushed away, it’s here to stay. Foot in Mouth


I’ve kept this article rather short and focused on the few points that bother me the most. I do think that C++ sucks, but as I’ve pointed out, it does suck for very good reasons. C++ turned out the way it did due to the numerous constraints and requirements that had to be respected and fulfilled. The main problem is that all the awful and outdated parts of the language have to be dragged along for all eternity in order to guarantee compatibility.

There are things in our society that mustn’t break, and most of them depend on software. And we need to consider our systems as a whole. Languages and their tool chains are part of it. We need to look into how we educate our developers and how we put emphasis on reliability5.

– Bjarne Stroustrup

With that in mind it should be easy to understand that C++ is a powerful tool that can be used to get almost any job done and it surely is the only language of this caliber. We’ll have to accept the fact that it still is an integral part of our profession and that it will stick around for many years to come – and that sucks.

…that’s why things will never change.

  1. http://thread.gmane.org/gmane.comp.version-control.git/57643/focus=57918 

  2. https://www.youtube.com/watch?v=JBjjnqG0BP8 

  3. http://www.stroustrup.com/bs_faq2.html#undefined 

  4. http://msdn.microsoft.com/en-us/magazine/cc500572.aspx 

  5. http://www.infoworld.com/t/application-development/stroustrup-why-the-35-year-old-c-still-dominates-real-dev-248457 

Related Articles

  • Scharlatan

    I would say that there is a very good reason to hate C++ (btw: tl;dr), but there is something in this language that wants me learn it. Java is much worse than C++, not to speak of .NET languages…

  • mike

    The thing I hate the most is the template system. It quickly becomes undecipherable.

    IMO, a programmer should approach C++ like they do Javascipt. Both languages are filled with badness, but if you approach both by only using the best parts, the end result can be elegant, simple and easy to maintain.

    • The template system is actually one of the most powerful and versatile features C++ has to offer. Still, I fully agree with you that template errors can be incredibly hard to comprehend.

    • feloneouscat

      SNOBOL is powerful language. Yet it is 99.999% indecipherable by anyone except the original programmer.

      Templates are a hack on top of a bad language. It doesn’t make it better, just messier.

      One of the developers I worked with had a requirement for the middleware that I was working on: NO TEMPLATES – his job was hard enough as it was and it SLOWED progress and created write-only code.

      So, yeah, powerful, but at the end of the day, costs businesses time and money.

  • Michael Pohoreski

    This is a joke us compiler guys love.

    There are only 2 problems with C++:

    1. Its design, and
    2. Its implementation.

    • Interestingly, I think the design and intentions of C++ were actually quite good in the beginning as it was intended to extend C, a language that was already popular. Basically a brilliant move that backfired hard. Nowadays, C++ is this ugly tumor-like beast that is impossible to get rid of. It has gotten too large and too widespread and the only way of controlling that monstrosity is to keep adding parts.

    • feloneouscat

      I would argue it started out as a tumor.

  • Michele

    Why you sucks
    you sucks for a very good reason :)

  • feloneouscat

    No, no, no and no.

    You are close, but miss a lot.

    The reason that C++ sucks is that it is a FAUX object oriented language. Many things that you CAN do with an object oriented language are impossible with C++ (unless you like hackery… no, I don’t like hackery).

    The reason is purely about runtime speed. At the time that C++ was designed, processors were horribly slow (compared to todays). OOP runtimes were dreadful. So all of the work was put in at compile-time in order to speed up run-time.

    Except for one thing. It meant that it was no longer OOP but pseudo-OOP. It kinda-quacked like a duck, kinda-looked like a duck, but really wasn’t a duck at all.

    For example, one aspect that was ripped from the hands of the developer was the ability to store the address to a function in a variable. Pretty damn useful. You can’t do that in C++. There are HACKS to do it, but natively, the language can’t.

    It is this “can’t” that makes the language so bad. Sure, you might think “I don’t need to store an address to a function in a variable” but try to build GUI API’s without that – it’s a PITA. So much so, that Qt uses a preprocessor to handle things that C++ can’t do.

    Wow. Now we’re having to write preprocessors to get over stuff the language is incapable of handling.

    I’ve written a lot of C++ code. There are parts of C++ I like. But for the most part, it is a broken language from the start. It is highly flawed. No one spent ANY time thinking through the problems with ctors or dtors (yeah, they said they did, but they didn’t).

    It’s a bad, broken, language.

    Compare it with Objective C (which has an ugly syntax) and it is no contest: Objective C is a true OOP language. You don’t even have to play games or hackery. But it is ugly as sin.

    • Ray Bornert

      You said: “… one aspect that was ripped from the hands of the developer was the ability to store the address to a function in a variable.”

      But then you said: “… you can’t do that in C++”

      You are a wrong and should be told so very loudly and in your face for failing to think before you comment. Nothing was ‘ripped’ from you.

      Of course you can store a function pointer the same as you can in C because anything you can do in C you can do in C++ (you knew that right?). I store function pointers regularly using standard C methods.

      So here are the words you should have used: “I wish C++ had improved the use of function pointers over and above the C methods.”

    • rabinnh

      I used to give this as a test question. Inside a class you define the function variable as a static pointer with a void* argument. When you call it in your instance from another method pass the “this” pointer. Call it a hack if you want, but many other languages use the “this” pointer in similar fashion.

  • GJT

    Start programming in D and see what happens. People that tried had a really big problem with it. There is the new D2 version which is the only version still being worked on right now. They’re patching it up. D1 is dead. If they don’t improve D it won’t take off.

  • Yakyak

    Schick Extreme or Mach 3? Just gimme a effin razor blade!

  • Moop

    Bjarne Stroustrup – “If C will shoot you in the foot, C++ will blow your leg off.”

  • Mike

    It’s only good design is manual memory management the rest of C++ can be kicked into the trash can. All those open source compilers, it’s amazing no one has simply made a new language that compiles down to C/C++. Getting the benefit of raw speed and the simplicity of anything other than Java.

  • Dan

    How can you possibly define behaviour for integer overflow without some massive performance hit. You would need to check the result of every increment or addition. Implementation defined would be fine. The stubborn C notion that the compiler should be allowed to reformat your harddrive or, simply remove the entire section of code because it might overflow is insane. How much code exactly should be removable if the end result of the whole program is undefined? Just enough to make it not undefined (but not knowable to the programmer either, so still undefined)? If any of the output is undefined all of it is, so why not optimize the whole code out and just replace it cout << "Game Over";