Do not worry about your difficulties in 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 arguments about it being difficult to learn, unnecessarily complicated and old.
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. 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 language for building mission-critical high-performance infrastructure, that is complex systems with predictable very strict real-time requirements and/or resource-constrained applications that are at the core of most industrial sectors.
C++ powers crucial 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 do optimizations, 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 facility 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++ is a sort of “hybrid” language that 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 and details that must be grasped in order to master this language, so the developer is expected to be skilled and educated enough to succeed. 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 caused by the fact that in a complex language with an intricate design, even the smallest change can lead to an “avalanche effect” where many other things must be changed as well to maintain consistency. So sometimes one gets the impression that the cost of learning all the effects produced by a new feature does not justify the benefits that the new feature is supposed to bring. I’ve often heard complains from C++ developers who wonder why something already complicated has been replaced with something else equally or even more complicated. And I must admit that this feeling has pervaded me too sometimes. It’s the consequence of 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 awkwardly incorporate new concepts from other languages while maintaining its old underlying design and philosophy, inevitably introducing more complexity. This is understandable for backward compatibility, but at some point a sharp break with the past is necessary.
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 to the standards, or when I find out there’s something I got wrong or simply don’t know. Because, among other things, with C++ you’re constantly learning, regardless of your level of expertise. Its continuous evolution and 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. 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.
 Updated survey from Stack Overflow