DEV Community

Dayvster 🌊
Dayvster 🌊

Posted on • Originally published at dayvster.com

In Defense of C++

The Reputation of C++

C++ has often and frequently been criticized for its complexity, steep learning curve, and most of all for its ability to allow the developers using it to not only shoot themselves in the foot, but to blow off their whole leg in the process. But do these criticisms hold up under scrutiny?

Well, in this blog post, I aim to tackle some of the most common criticisms of C++ and provide a balanced perspective on its strengths and weaknesses.

C++ is "Complex"

C++ is indeed a complex language, with a vast array of features and capabilities. For any one thing you wish to achieve in C++, there are about a dozen different ways to do it, each with its own trade-offs and implications. So, as a developer, how are you to know which approach is the best one for your specific use case? Surely you have to have a deep understanding of the language to make these decisions, right?

Not really... I mean, don't get me wrong, it helps, but it's not a hard requirement. Premature optimization is the root of all evil, and in C++, you can write perfectly fine code without ever needing to worry about the more complex features of the language. You can write simple, readable, and maintainable code in C++ without ever needing to use templates, operator overloading, or any of the other more advanced features of the language.

There's this idea that for everything you want to do in any programming language, you need to use the most efficient and correct approach possible. Python has this with their pythonic way of doing things, Java has this, C# has this, and Go has this. Heck, even something as simple as painting HTML onto a browser needs to be reinvented every couple of years and argued about ad nauseam. Here's the thing, though, in most cases, there is no one right way to do something. The hallowed "best approach" is often just a matter of personal or team preference. The idea that if you just write your code in the "best" and correct way, you'll never need to worry about maintaining it is just plain wrong.

Don't worry so much about using the "best" approach; worry more about writing code that is easy to read and understand. If you do that, you'll be fine.

C++ is "Outdated"

C++ is very old, in fact, it came out in 1985, to put it into perspective, that's 4 years before the first version of Windows was released, and 6 years before the first version of Linux came out, or to drive the point even further home, back when the last 8-bit computer was released. So yes, C++ is quite old by any standard. But does that make it outdated?

Hell no it's not like C++ has just been sitting around unchanged from its 1985 release. C++ has been actively developed and improved upon for over 40 years now, with new features and capabilities being added all the time. The most recent version of the C++ standard, C++20, was released in 2020 and introduced a number of new features and improvements to the language. C++23 is also on the horizon and is expected to bring even more improvements to the language.

Key among these improvements are modules, concepts, ranges, and coroutines. These features bring modern programming paradigms to C++, making it more powerful and expressive than ever before.

But Dave, what we mean by outdated is that other languages have surpassed C++ and provide a better developer experience.

Matter of personal taste, I guess, C++ is still one of the most widely used programming languages with a huge ecosystem of libraries and tools. It's used in a wide range of applications, from game development to high-performance computing to embedded systems. Many of the most popular and widely used software applications in the world are written in C++.

I don't think C++ is outdated by any stretch of the imagination; you have to bend the definition of outdated quite a bit to make that claim.

C++ is "Unsafe"

Ah, finally, we get to the big one, and yes, I will draw comparisons to Rust as it's the "memory safe" language that a lot of people claim will or should replace C++.

In fact, let's get the main point out of the way right now.

Rewrites of C++ codebases to Rust always yield more memory-safe results than before.

Countless companies have cited how they improved their security or the amount of reported bugs or memory leaks by simply rewriting their C++ codebases in Rust.

Now is that because of Rust? I'd argue in some small part, yes. However, I think the biggest factor is that any rewrite of an existing codebase is going to yield better results than the original codebase.

When you rewrite a codebase, you have the opportunity to rethink and redesign the architecture, fix bugs, and improve the overall quality of the code. You get to leverage all the lessons learned from the previous implementation, all the issues that were found and fixed, and you already know about. All the headaches that would be too much of a pain to fix in the existing codebase, you can just fix them in the new one.

Imagine if you will that you've built a shed, it was a bit wobbly, and you didn't really understand proper wood joinery when you first built it, so it has a few other issues, like structural integrity and a leaky roof. After a few years, you build a new one, and this time you know all the mistakes you made the first time around, so you build it better, stronger, and more weatherproof. In the process, you decide to replace the materials you've previously used, say for example, instead of using maple, you opt for oak. Is it correct to say that the new shed is better only because you used oak instead of maple? Or is that a really small part of the overall improvement?

That's how I feel when I see these companies claim that rewriting their C++ codebases in Rust has made them more memory safe. It's not because of Rust, it's because they took the time to rethink and redesign their codebase and implemented all the lessons learned from the previous implementation.

But that does not deny the fact that C++ is unsafe.

Yes, C++ can be unsafe if you don't know what you're doing. But here's the thing: all programming languages are unsafe if you don't know what you're doing. You can write unsafe code in Rust, you can write unsafe code in Python, you can write unsafe code in JavaScript.

Memory safety is just one aspect of safety in programming languages; you can still write unsafe code in memory-safe programming languages. Just using Rust will not magically make your application safe; it will just make it a lot harder to have memory leaks or safety issues.

The term "unsafe" is a bit too vague in this context, and I think it's being used as a catch-all term, which to me reeks of marketing speak.

Can C++ be made safer?

Yes, C++ can be made safer; in fact, it can even be made memory safe. There are a number of libraries and tools available that can help make C++ code safer, such as smart pointers, static analysis tools, and memory sanitizers. Heck, if you wish, you can even add a garbage collector to C++ if you really want to(please don't).

But the easiest and most straightforward way to make C++ safer is to simply learn about smart pointers and use them wherever necessary. Smart pointers are a way to manage memory in C++ without having to manually allocate and deallocate memory. They automatically handle the memory management for you, making it much harder to have memory leaks or dangling pointers. This is the main criticism of C++ in the first place.

C++ is Hard to Read

Then don't write it that way. C++ is a multi-paradigm programming language; you can write procedural code, object-oriented code, functional code, or a mix of all three. You can write simple and readable code in C++ if you want to. You can also write complex and unreadable code in C++ if you want to. It's all about personal or team preference.

Here's a rule of thumb I like to follow for C++: make it look as much like C as you possibly can, and avoid using too many advanced features of the language unless you really need to. Use smart pointers, avoid raw pointers, and use the standard library wherever possible.

You can do a heck of a lot of programming by just using C++ as you would C and introducing complexity only when you really need to.

But doesn't that defeat the whole purpose of C++? Why not just use C then?

C++ is a superset of C you can write C code in C++, and it will work just fine. C++ adds a lot of features and capabilities to C. If you were to start with C, then you are locked with C, and that's fine for a lot of cases, don't get me wrong, but C++ gives you the option to use more advanced features of the language when you need them. You can start with C and then gradually introduce C++ features as you need them. You don't have to use all the features of C++ if you don't want to.

Again, going back to my shed analogy, if you build a shed out of wood, you can always add a metal roof later if you need to. You don't have to build the whole shed out of metal if you don't want to.

C++ has a confusing ecosystem

C++ has a large ecosystem built over the span of 40 years or so, with a lot of different libraries and tools available. This can make it difficult to know which libraries and tools to use for a specific task. But this is not unique to C++; every programming language has this problem.

Again, the simple rule of thumb is to use the standard library wherever possible; it's well-maintained and has a lot of useful features. For other tasks like networking or GUI development, there are a number of well-known libraries that are widely used and well-maintained. Do some research and find out which libraries are best suited for your specific use case.

Avoid boost like the plague. Boost is a large collection of libraries that are widely used in the C++ community. However, many of the libraries in boost are outdated and no longer maintained. They also tend to be quite complex and difficult to use. If you can avoid using boost, do so.

Unless you are writing a large and complex application that requires the specific features provided by Boost, you are better off using other libraries that are more modern and easier to use. Do not add the performance overhead and binary size bloat of Boost to your application unless you really need to.

C++ is not a good choice for beginners

Programming is not a good choice for beginners, woodworking is not a good choice for beginners, and car mechanics is not a good choice for beginners. Programming is hard; it takes time and effort to learn, as all things do. There is no general language that is really good for beginners; everything has its trade-offs.

Fact is, if you wanna get into something like systems programming or game development then starting with Python or JavaScript won't really help you much. You will eventually need to learn C or C++.

If your goal is to become a web developer or data scientist, then start with Python or JavaScript.

If you just want a job in the programming industry, I don't know, learn Java or C#, both great languages that get a lot of undeserved hate, but offer a lot of job opportunities.

Look, here's the thing: if you're just starting out in programming, yeah, it's gonna be hard no matter what language you choose. I'd actually argue that starting with C or C++ is far better than starting with something that obscures a lot of the underlying concepts of programming, I'd argue further that by starting with Python or Javascript you are doing yourself a disservice in the long run and trading off the pain of learning something when your understanding of a topic is still fresh and malleable for the pain of learning something later when you have a lot more invested in your current understanding of programming.

But hey, that's just my opinion.

C++ vs Rust: Friends or Rivals?

Rust has earned a lot of love in recent years, and for good reason. It takes memory safety seriously, and its borrow checker enforces discipline that C++ often leaves to the programmer. That said, Rust is still building its ecosystem, and the learning curve can feel just as steep — just in different ways. C++ may not prevent you from shooting yourself in the foot, but it gives you decades of battle-tested tooling, compilers, and libraries that power everything from Chrome to Unreal Engine. In practice, many teams use Rust and C++ together rather than treating them as enemies. Rust shines in new projects where safety is the priority, while C++ continues to dominate legacy systems and performance-critical domains.

Is C++ Still Used in 2025?

The short answer: absolutely. Despite the constant chatter that it’s outdated, C++ remains one of the most widely used languages in the world. Major browsers like Chrome and Firefox are still written in it. Game engines like Unreal run on it. Automotive systems, financial trading platforms, and even AI frameworks lean heavily on C++ for performance and control. New standards (C++20, C++23) keep modernizing the language, ensuring it stays competitive with younger alternatives. If you peel back the layers of most large-scale systems we rely on daily, you’ll almost always find C++ humming away under the hood.

Conclusion

C++ is a powerful and versatile programming language that has stood the test of time. While it does have its complexities and challenges, it remains a relevant and widely used language in today's tech landscape.
With the right approach and mindset, C++ can be a joy to work with and can yield high-performance and efficient applications. So next time you hear someone criticize C++, take a moment to consider the strengths and capabilities of this venerable language before dismissing it outright.

Hope you enjoyed this blog post. If you did, please consider sharing it with your friends and colleagues. If you have any questions or comments, please feel free to reach out to me on Twitter.

Top comments (40)

Collapse
 
dyfet profile image
David Sugar

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.

Collapse
 
dayvster profile image
Dayvster 🌊

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.

Collapse
 
olvap profile image
Pavlo Mur • Edited

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))

Collapse
 
dyfet profile image
David Sugar

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.

Thread Thread
 
olvap profile image
Pavlo Mur

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)

Collapse
 
jodaut profile image
José David Ureña Torres

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.

Collapse
 
andrescass profile image
Andres Cassagnes

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

Collapse
 
dayvster profile image
Dayvster 🌊

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.

Collapse
 
jlburgos profile image
Juan Burgos • Edited

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:

  • Patience when learning the language and the tool-ecosystem.
  • Mindfully using only those language constructs that you actually need.
  • Less dogma about what is considered arbitrarily "better" or "safer".
Collapse
 
dayvster profile image
Dayvster 🌊

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 :)

Collapse
 
optimisedu profile image
optimisedu

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

Collapse
 
dayvster profile image
Dayvster 🌊

thanks, that's a huge compliment, appreciate it.

Collapse
 
teminian profile image
Robert Teminian

Bravo. As a C++ developer myself I can't agree with you more.

Collapse
 
dayvster profile image
Dayvster 🌊

Appreciate it!

Just for my curiosity how many years experience would you say you have with C++ ?

Collapse
 
teminian profile image
Robert Teminian

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?"

Thread Thread
 
dayvster profile image
Dayvster 🌊

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

Thread Thread
 
teminian profile image
Robert Teminian

Sounds fun! I look forward to seeing your followup post.

Collapse
 
dimonic profile image
dimonic

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.

Collapse
 
dayvster profile image
Dayvster 🌊

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.

Collapse
 
dimonic profile image
dimonic

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.

Thread Thread
 
dayvster profile image
Dayvster 🌊

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.

Collapse
 
eagerm profile image
Michael Eager

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.

Collapse
 
josephdailey11 profile image
JDailey

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.

Collapse
 
sephyi profile image
Sephyi

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.

Collapse
 
elanatframework profile image
Elanat Framework

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.