Do not worry about your difficulties with C++. I can assure you mine are still greater.
This quote (shamelessly plagiarized) neatly summarizes the characteristics of this language. C++ is surely not for the faint of heart, and mastering it to a degree where you can get the full power that it is capable to deliver requires a considerable amount of time and plenty of hands-on implementations in all of its esoteric aspects. This is the main reason why it’s often looked upon with a sense of disdain, especially by techno-hipsters who will throw at you argumentations about it being difficult to learn, unnecessarily complicated and old. In that exact order.
I will not discuss the meaningless concerns about its age, as languages do evolve and today’s C++ is not exactly the same as the one Stroustrup came up with in the ’80s, and also because age is not a suitable metric to measure the fitness of a technology to current needs. Python, for example, often labeled as “modern” and very much en vogue nowadays, is more or less C++’s contemporary. I will not make out of context comparisons with other languages either as that’s stuff for religious extremists who would claim that a hammer is better than a screwdriver. What I will do is express my thoughts about a language that, whether we like it or not, has made its strong mark in the history of computing and is, undoubtedly, a big commercial and industrial success.
One of the most recurrent criticism is about it having an unnecessarily steep learning curve compared to other languages. While this may be true, often these criticisms are stemming from incoherent comparisons or even plain ignorance. I’m puzzled every time I see it compared to other languages that have a completely different and very limited application domain, where one paradigm is taken to the extreme and sterilized to its purest form, or even to scripting languages for “increasing productivity”, “reducing time to market”, “building apps in one day”, etc.. Basically like comparing apples to oranges. C++ is not a language aimed to please the marketing and sales departments, nor to make your life easier as an Engineer by taking from you technical knowledge. It’s a powerful complex language for building high-performance infrastructure, that is critical systems with very strict real-time requirements and/or resource-constrained applications that are at the core of most industrial sectors.
C++ powers mission critical infrastructure, such as data centers, avionics equipment, space missions, medical devices, the backbone of the internet and the core of most AI platforms, to name a few. And when you build such infrastructure you’re put on the border line between the need for low level computation to deal with the underlying implementation, and more abstract paradigms to manage the complexity of the architecture. C++ provides all that in one language without the need to throw in extra middle-ware. It provides a way for creating different levels of abstraction allowing the representation of systems at varying degree of detail, from raw bits to generic abstract data types. Something that no other language can do as efficiently.
I agree with the criticism about it having several inconsistencies and contorted ways of doing some things. I always had a hard time working around them. Admittedly, it’s never been a “clean” language. But these oddities find a justification in the nature and origin of the language itself. C++ was built on top of a language that’s just an inch higher level than assembly (C) by extending it with OOP and other abstraction paradigms, and this integration between the low-level approach of C and the high level concepts of C++ has given rise to idiosyncrasies that have haunted the language since its inception. Bug-prone memory management, somewhat redundant data referencing, a verbose syntax to express simple constructs and compilation issues (especially cross-compilation) are a few mental obstacles that used to make the learning curve steep. However, with modern C++ many legacy approaches haven been significantly improved and now the programmer is no longer forced to implement “by hand” many features that should have been natively supported.
C++ was born as a general purpose, multi-paradigm programming language with a strong bias towards systems development with guaranteed high-performances. It provides a lot of flexibility allowing coding of applications in a wide variety of domains, in many programming styles, at many levels of detail and with benchmark results that are hardly beatable with proper design compared to other languages in the same category. But to achieve all this there is a price to pay, and that comes in the form of complexity. There are many programming concepts that must be grasped in order to be able to properly use this language, so the developer is expected to be skilled and educated enough to undertake the task. Combine this with its inherent idiosyncrasies and the burden on the developer’s shoulders can be heavy. But that’s unavoidable if you want to enjoy the power that only C++ provides.
Another reason that contributes to its perception as a complicated technology to learn is the fact that in a language that’s feature-rich and has quite an intricate structural design, even the smallest change can lead to an “avalanche effect” where you have the impression that the cost of learning the effects produced by the introduction of a new feature and adapt to them does not justify the benefits that the new feature is supposed to bring. I’ve often heard complains from C++ developers who feel that something already complicated has been replaced with something else that looks even more complicated. And I must admit that this feeling has pervaded me too several times. It’s the consequence of this avalanche effect, caused by the characteristics of the language.
But C++ has been undergoing a long process of modernization, and starting with C++11 in particular it has seen significant improvements that have made many things easier. It is trying to become cleaner and more intuitive while preserving its power. Things have changed quite substantially from earlier versions and, despite some legacy concepts still bugging its new face (and that most likely will be part of it forever for commercial reasons), it is now a more polished and approachable technology. However, sometimes it feels like it is striving to achieve some level of universality by trying to embrace all sorts of paradigms even when they do not fit the underlying design and philosophy, inevitably requiring the introduction of more complexity. A sort of super set of all languages. But that is just my opinion.
I have been using C++ for a long time now and have done quite a bit of sophisticated work with it, yet at times I’ve been feeling like a beginner when trying to grasp new rules and changes that disrupt previous standards, or when I find out there’s something I got wrong or simply don’t know. Because, among other things, it feels like with C++ you’re constantly learning, regardless of your level of expertise. Its peculiarities force you to do so, and that can be a frustrating experience for some people, especially for those coming from simpler languages. It can put you in a position where it’s easy to shoot yourself in the foot if you don’t know exactly what you’re doing. A bit like driving a Hyundai and a Lamborghini. You may feel you can drive both equally well. Until you step harder on the accelerator. That’s also the reason why, unlike with other languages, you must think twice before labeling yourself as an “expert C++ programmer”.
Despite all its dark sides, I love the power that it puts in your hands. I like its inner spirit, the “…smaller and cleaner language struggling to get out…“ buried under a layer of oddities that the various modern standards are trying to remove. All in all, even though I moved on to other languages, I still remain a C++ supporter. It’s a love/hate relationship that will probably last for long.