The Reputation of C++
C++ has often and frequently been criticized for its complexity, steep learning curve, and most of all for its abi...
For further actions, you may consider blocking this person and/or reporting abuse
While C++ is complex, it is also often effectively expressive of that complexity. For some things I have also found it better to go back to pure C. There are things I love about go, too. But Rust would now be my very last choice for programming.
This is why I try to adhere to the just write C++ as if you were writing C until you need some of it's more complex features.
you can get really far with just imitating C in C++
Rust on the other hand for me is the opposite of that, you start with complexity right out of the gate.
Pure C is perfect unless one starts to invent own "OOP in C", own "inheritance" like stuff around... And everyone "reinvents" this in their own custom way:
Some teams/projects/libraries place function pointers directly into data structures, others maintain separate "VMT-like" stuff manually... Some cast pointers back and forth, some use ugly Base_Method(&objPtr->base.base.base) approach, some write inline wrappers in every header for every "derived" class to call base's "methods"...
...and all that stuff is done and tracked manually including calling of "destructors" and ultimately "everyone must be very careful to track the life time manually" (some even use AddRef/Release like API imitating "smart pointers", but this is still manually maintained boilerplate hell)...
This all is mixed with all workarounds and implicit conventions that are in many cases not written in any docs at all (!) and one must figure out this by literally "reverse engineering" the code. But even if rules are written, still everyone tries to "shortcut" and skip some rules by inverting own undocumented "algebraic types" as "tagged unions" with own implicit conventions and special ownership rules...
Clearly even C++ classes are much better instead of all those custom "inventions" of "OOP in C". Also std::variant is much better than all those manually maintained "tagged unions" as custom "algebraic types"!
Who owns what? When I shall free that resource? Etc... (if there are no destructors "by design" there shall be at least "go-lang-like defer" supported by the language)... Yes C++ is not as perfect in all of this, as Rust, but still I can at least ban copy and assignment everywhere and enforce "rule of 5" instead of all those "be careful" and "watch your step" everywhere!...
Yep, C++ standard containers are far from being perfect,
but "pure C way" for manual linked list management (especially when one's data are members of multiple linked list chains simultaneously) while one manages casts from nodes to the whole data structures with a set of ugly macros, for the most of the real world projects this is just an overcomplication that makes project support kind of hell (unless ones name is Linus, but with adding Rust I think he is heading the right direction))
Indeed the main reason I migrated from C to C++ in the 90's touched upon this. In the 80's I did a Ui toolkit, VU, which, like so many similar things at the time, of course was doing object oriented code in pure C. OOP in C is about an artificially enforced discipline and style since C does nothing to "enforce" correct use and practice. Obviously, that made C++ seem far more intuitive a choice. But there are also many things you can do in pure C, too, and sometimes do so much more efficiently without any abstraction or large runtime overhead.
The niche for C is very close with "stripped out C++" (the so called "Arduino Scripting language" is actually C++, one can use even lambdas and templates, but no "iostreams" and no C++exceptions)).
Still, definitely any external binary API (exports) must be in C, to be perfectly interoperable practically with "anything" (not only because of name mangling in C++, but also because of binary layouts, that are broken, unless one follows "close to C" rules... exceptions also cannot cross module boundaries, etc... The only known binary interoperable C++ stuff looks to be COM from MS, that abuses the fact that VMT layout is the same for the selected platform)
Great article! C++ is a very important language and is widely used actually. As you mentioned, it does not compete with Java, Python or JavaScript. The all serve to different areas of software. C++ is great for Linux/Unix programming for example, or systems where memory management and speed are crucial. Or when you need very small executables. Java and Python cannot offer that xD.
That's the whole point. I always say to my junior coworkers, there are no better or worse languages, there are languages better for specific uses.
There is no language that fits perfectly in all the circumstances
it's still the language that holds up the most important infrastructure and projects well C++ and C.
It's gonna take a while for any language to replace that, Zig might.
I don't know if Rust can it's nice and all but binaries that are 3-5x the size and often slower just don't seem like the way forward to me.
C++ is only complex in the variety of ways you can solve any arbitrary programming problem. If you only use the tools and language constructs that you actually need, then the language is only as complex as you need it to be. This isn't even specific to C++. Every other language that has existed for decades has "issues" the people tend to complain about. Only reason newer languages are sometimes considered safer is that they stand on the shoulders of giants, have carved out a specific niche instead of being a generalist language, or hide so many details of the underlying behavior (looking at you python) that memory management is likely not your primary concern.
Ultimately, the best antidote to fear and confusion, especially when it comes to learning "difficult" languages like C++, is as follows:
Precisely!
Well put, this is basically one of the points I tried making in the article but you articulated it quite well here.
Thank you :)
This is a brilliant article your voice and points ring very clearly and brings up the sad facts that we are getting a huge amount of content the is at least partially ran through a neural net giving it the same homogenised voice I have to apologise for my lack of punctuation and hope this makes sense I'm currently time looking for a new Hobby and I think I have matured into being ready to learn C++ from the ground up again a first try learning C++ in 1996 I was five years old and using a textbook eventually became a pretty bad program using basic an eventually SEO got me into performance optimisations for business again however since JavaScript is where my market was I specialised in scripts than a compiled language with pointers and other such low level functionality I have a broken hand and a lot of time to kill any suggestions on a good place to learn C++ from the Ground Up would be really appreciated just extremely frustratingly slow.
great article truly
thanks, that's a huge compliment, appreciate it.
Bravo. As a C++ developer myself I can't agree with you more.
Appreciate it!
Just for my curiosity how many years experience would you say you have with C++ ?
For professional use, it's been 5~6 years.
But, if I include my "prelude period", I'd say "have you ever tried Turbo C 2.0 with 5.25 inch floppy diskette?"
Hahah fair, thank you.
I'm putting together another blog post in the near future, I've noticed an interesting trend in how people with different experience levels responded to this particular post. Think it might be worth a deeper dive
Sounds fun! I look forward to seeing your followup post.
I was nodding to most of the things you were saying, until you got to boost. Boost is not bloated at all - in nearly all cases, it is only headers - no binaries at all. It is also under constant ongoing development, and not "out of date" at all. Time after time, its best features get adopted as part of either the language standard, or the standard library - including those smart pointers you raved about.
Please take some time to research boost before you malign it.
The one criticism I would say is fair is that its documentation seems opaque at first.
I do a lot of embedded or embedded-like programming where boosts overhead does not lend itself well to the use case.
So naturally I do not like boost.
Boost to me fits this strange use-case. So basically boost usually comes into play when you are developing desktop applications and web applications, which is fine.
How do I explain this without sounding like an asshat.
I think boost allows developers to create software where C# and Java would be a solid choice as well at which point why not just go for C# or Java?
But I do appreciate your feedback, do not feel slighted by my personal distaste for boost, I don't look down on people who do use it nor should anyone.
I write primarily embedded software (for ground penetrating radar). I also create high performance C++ libraries for signal processing for consumption by python for physicists to use (using the boost-python wrappers). I use the same core code on three different platforms (embedded arm, cloud and desktop).
I have measured many use cases for boost over the years, and have found zero cases where boost makes the code significantly larger than any alternative I could find. That is not to say it could not happen, but I have used dozens of boost "libraries" (mostly, as I said, template headers) and not seen the problems you described. I would hate to accuse anyone, but I have found the so called bloat problem to be a myth.
It's not exactly a myth.
Here's the thing, you can absolutely import individual boost libraries and keep the impact on the binary size fairly minimal. But it will still be enough of an impact where it will be very hard to excuse using it if you want your entire binary to fit on a device that has somewhere between 64Kb to a max of 8Mb of Flash.
and the 8MB Flash ROM, most consumer grade vehicles will have MCUs with about 128-512KB of Flash.
There is no C++ boost library that will lend itself to this. Or rather very few, and their capabilities are fairly limited and trivial to write on your own.
So my perspective on boost is heavily colored by this, now if your experience is using boost for desktop applications, network programming etc. etc. that's a different story, I can see why you'd like boost in that case.
The advice to developers, especially ones new to C++, to write in a constrained subset of C++ is one which I have offered many times in the past. But while you can write C programs, using the C library functions like printf() or your own linked lists functions, why compile them as C++ instead of C? There's little benefit in pretending that a C program is C++.
Constraining the C++ features which you use may reduce the complexity of your particular program, but it does not reduce the complexity of the C++ language. There are a few caveats with this advice.
First, the inherent complexity of C++ cannot be easily hidden. As soon as you use any features not in C, such as streams, STL containers, classes, etc., that complexity is incorporated into your program. Because the various functional features of C++ are not independent, generally using any C++ feature brings in all of C++ complexity. This results in cryptic error messages and hidden operations.
Second, this advice only applies to new single-developer programs. I think that few people have that luxury. I work with C++ programs with hundreds of files and hundreds of thousands of lines of code, developed by tens to hundreds of people over the space of decades. While I can limit the C++ features I use when I add code, I can't control what other developers have done in the past. If they have used multiple inheritance, questionable operator overloading, or friend classes liberally, I might think that this is bad form, but if I want to fix a bug or add functionality, I have to understand these features.
C is a small language, easy to understand in its entirety, with few dark corners. What you see is what you get. C++ is a large language, with many areas which are complex and not easy to understand. Often, what you see gives little clue about what is happening out of sight. Here are some examples.
If I see the statement
Foo bargle;
in a C program, I know that Foo must be a type and bargle is either data or possibly the declaration of a function named bargle(). There's no code executed, except perhaps to reserve some stack space depending on where this statement appears. In C++, this may or may not create an object in memory, it could declare a function, and, if Foo is a class, may execute a constructor which has unbounded complexity. If this statement appears outside of a function, then this constructor runs before the program starts at main().
[I work on a program where creation of sub-processes and the setup of communication between these process is all done "magically" in constructors for global objects before the program starts at main().]
If I see this statement
razzle(99);
in C, I can assume that razzle is a function and it is being called with an integer argument. In C++, razzle might be a function, it might be a scalar type (such as int) which is being set to 99, or it might be constructor for a class, executing whatever code is in the constructor. (Incidentally, distinguishing between the multiple possible meanings of this kind of statement makes parsing C++ a challenge.)
While setjmp/longjmp is a horror, in C longjmp() does exactly two things: it resets the stack pointer to the saved value and continues after the setjmp() call. It's your responsibility for any needed cleanup. Exceptions in C++ are a huge improvement, but when a throw statement is executed, there is a large amount of hidden processing to walk the stack and do cleanup in each function which needs it. This is a very complex process, one which is hidden from sight.
C++ is a complex language which takes a long time for someone to be proficient with. It's not easy to create a functional subset (there was an effort to create Embedded C++ years ago, essentially "C with Classes" as C++ was originally designed). My recommendation for new programmers is that C++ is a good second language, after one has learned the basics of problem decomposition, program design, data structures, and other concepts.
I took a year of programming language and choose C++ over Java; however, I found my i5 machine in windows was getting in the way. I didn't finish, but I think my love for Linux will bring be back on my own. I think programming is hard, but if you look at it all if else statements are similar. I thought it was easier than BASIC in the 80's to be honest.
One thing I’ve never understood about C++ is why so many projects still stick to outdated versions of the language. I’ve seen projects started only a few years ago that were already locked to something like C++11 (from 2013). Am I missing something here? I’d really appreciate some insight, because I honestly don’t get it. Or maybe I’ve just had bad luck and this isn’t how things usually are in the broader C++ world.
I’ve worked with C++ already myself, but at this point I wouldn’t recommend it to anyone unless they have a very specific, unavoidable reason. If someone already has solid experience in C or C++, that’s different. But for newcomers, I don’t see a single strong argument in its favor—only a long list of potential pitfalls, ranging from mildly annoying to seriously painful.
C++ is hard to use on the web. I couldn't find any C++ web frameworks to test the C++ WebForms class.
C++ was the first programming language I learned in college, although I later learned programming at a reasonable level by reading a useful book on the BASIC programming language.
C was my first programming language, but C++ is the language of my heart.
I work in safety, critical systems and there is no competitor to C/C++ in those areas.
Also in one of the leader measurement instrumentation systems, the language is C++.
Moreover, is a really beautiful and elegant language if you put the effort to write the code.
Great article, very good points, that I will take and use in my future discussions about programming languages.
Why do you think poorly of Ada for safety critical systems?
The first oop lang I encountered was C++.I like the lang.
But, feel overwhelmed to use the build systems.
Do you have any suggestions on it?
the build system is arguably the biggest weakness of C++
Sadly we are mostly stuck with Ninja / CMake for the foreseeable future.
I would say that not the C++ language is complex, but the frameworks we use bring complexity. The language is very flexible and that's why I love it.
Eeeh it can spiral out of control pretty fast if you try to use too many of C++'s features.
But that's the secret, you don't need to you should just write it as C until you need more complexity.
I like how you point out it’s still evolving (modules, coroutines, etc.) and that complexity doesn’t always mean bad.
Appreciate it, thank you.
People love to bring up this point against C++ and even C that they are old. Even though they have been receiving a lot of updates and new features fairly regularly.
C++ isn’t perfect..but it’s battle-tested and still powering some of the coolest stuff out there...
Totally agree, C++ doesn’t have to be super complicated. Stick to what you need, and it’s still super powerful and flexible for real projects.
New versions of C++ add complexity and, at the same time, add safe memory features, so, you have to choose what kind of C++ you want to keep.
good job!
aww, thanks!
This is mistagged: it should be tagged
#cpp
.#c
is for C.😎👌🔥
In fact, despite the complexities and some of the challenges I face, I enjoy writing code in this wonderful language. No, it has not been rendered obsolete by time; even after 40 years, it is still considered a powerful and sustainable language.