How to learn C plus plus
I used to work a lot in C++, I don't anymore and haven't for almost 3 years, but occasionally I end up giving advice to people that want to learn the language, so I thought I might as well compress it all into an article.
I'm assuming here that you know nothing about C++, but are somewhat familiar with programming in some higher-level languages. If you aren't, I'd recommend you try to learn python first, or some other "easier" language of your choice.
i - Why is C++ annoying to learn?
C++ is amongst the oldest and most popular languages in the world.
Unlike other old languages, it's very much under active development, with a huge design committee of researchers, academics and engineers working in a variety of sectors. It's treated as a first-class citizen by arguably the "best" compilers on the market (clang and gcc) and it grows to engulf a lot of high-quality concepts that pop up in various languages and libraries. What constitutes C++ in 2021 is almost wholly unrelated to what it was in the 80s.
On top of garbling up new features like there's no tomorrow, C++ tries to maintain backwards compatibility with the prehistoric versions of itself.
So I don't think it's unfair to say that C++ might be the most convoluted and complex programming language. Trying to "learn the language" might is a misguided goal, one ought to try and learn the basics, then delve deeper into whatever subjects they need to get mastery of. It's better to treat it as a very advanced toolkit rather than as a language one can be fluent in. Even its creator would admit that nobody understands it fully anymore.
The difficulty of learning C++ is compounded by a few things:
- Bad teachers are often known to use it as a starting point for CS students, these teachers themselves usually don't understand C++, but they write books, blogs and reference websites. Their students don't understand C++, but they ask and answer stack overflow questions, or even write blogs about it. So the internet is polluted with bad quality material.
- Even "good" references grow outdated but acquire SEO capital as they decay. The best C++ book from the 2000s is almost certainly worst than a mediocre one from the 2020s. But people often don't bother to update or unpublish references. To top this whole thing of the "++" bit of the name, and the many alternatives spelling that grew out of its url unsafeness, add that extra bit of difficulty to searching.
- Different companies and teams have very different "takes" on how to write C++, so even good up-to-date developers will have widely differing views and opinions on how to learn the language and what constitutes best practices under various circumstances.
All of this is to say that you should learn C++ in a very "defensive" way, the default should be to distrust most sources and carefully vet ones that seem good.
ii - The basics
I did a bit of vetting of source myself, they are a bit outdated by now, I'm sure, but I'd tentatively recommend the following 4 starting points to delve into the language:
Cppreference.com is the unofficial official documentation and contains almost anything you need to know about the language and the standard library. It should be your first go-to for any questions. It's a bit difficult to dig through, but the "easier" websites are usually outdated and often contain some outright falsehoods on top.
Stroustrup (the guy that made C++) often writes "introductory" books for C++, the latest one being the second edition of "A tour of C++", which is aimed at beginner programmers and published in 2018, so it's a very good starting point. But if by the time you read this he publishes a new book, read that instead.
Scott Mayer's published a fairly old book that detailed important differences between C++03 and the 11 & 14 version. He's an amazing writer and speaker, but afaict no longer works in the C++ space. I tentatively recommend it as a guide for understanding the "evolution" process that C++ goes through, which is a critical lens for learning and comprehending it. But I'm afraid this book is already quite outdated, and in a few years, it will likely fall into the "harmful information" bucket, take with a grain of salt, ymmv.
Finally, Stack Overflow is actually a fairly good C++ resource, as long as you are asking the right questions. There are a lot of insanely smart people, or at least people with an insane obsession for C++, that are laying in wait to pounce on any half-interesting question you ask, and most questions you'd want to ask are already asked and have a lot of up-to-date detailed answers and debates. Look at the year of the answer and er towards preferring newer answers. The Stack overflow documentation for C++ was very good, and while it's starting to be deprecated, I still think it's worth a look for the next few years.
More broadly, there are a few base concepts one ought to understand in order to start using C++, some of which you might be familiar with, but most will be quite arcane to you if you learned them from other languages. These are:
- Classes - C++ has a very powerful (and arguably bad?) take on inheritance and how classes work. Ideally, drop whatever you knew about classes and try to learn them with fresh eyes.
- Types - The type system of C++ is, again, powerful but messy. It's not that hard to get and understanding it and the built-in types is critical.
- Templates - A bit of a misnomer for the Turing-complete compile-time language contained within C++ used for working with types, names and definitions. Sometimes called "metaprogramming"
- Macros - Which are fairly similar to the ones in C, and usually discouraged in favour of template-based metaprogramming.
- Functions, lambdas and scopes - These are probably different from the things bearing the same names in the languages you're familiar with.
- Understand the difference between
.h
and.cpp
files as well as between static and dynamic linking (see 2 headings bellow for some caveats on that). - Referencing system - Aka the
*
s and&
s you'll see thrown about in any C++ code. Don't bother too much with pointers (*
), since they have been replaced by smart pointers which are more intuitive to use. But understanding references and passing by reference is critical. - Mutability - which boils down to how the keywords
const
andconstexpr
used together with the above-mentioned pointers and references. - Understanding how the stack and free memory (heap) differ is rather critical, but you should have already gotten that once you navigated all of the above concepts. As a follow-up, you should try and understand move semantics, but you may find it confusing to read about them at this stage, ymmv.
You can probably get a decent grasp of all of these in 1 to 100 hours and they will serve as a good foundation for building the rest of your knowledge. The 4 references provided should contain information on all of them.
iii - Libraries
Remember, C++ is old, messy and used by a lot of important, complex and large codebases.
Writing python at google is different from doing it at Facebook, company cultures differ, the high-level libraries differ, the stay guides differ. But the C++ used at Google is probably better treated as a whole different language than that used at Adobe or Facebook.
I mentioned this point to coat in it the idea that, ...sigh, C++ didn't have a standard library for a long time... and when it got one it was kinda sucky at first, and it still is in many places... so, ahem, yeah, most big companies basically have their own standard libraries.
Depending on your workplaces you will be using strings, maps, hash maps, arrays, smart pointers, decimals, vectors and other such basic structures and utility functions from your company's hand-made standard library.
The good news here is that most people are migrating to a combination of the STD/STL (C++'s official standard library) and Boost (a more experimental library that contains additions to the STD and is used as a testing ground for STD candidates).
Other than that, there are various other "standard libraries" popular with various industries, QT for anything involving GUIs, Juice for multimedia and so on.
Ideally, you should try and have a look around C++s STD, then learn whatever "standard" libraries your workplace uses.
What about other libraries?
The ecosystem is quite similar to the one in Node, with many libraries competing to do almost the same thing, so library choice will be an important thing to consider.
Unlike node, there are very few libraries overall and most of them have large scopes and steep learning curves, so you might well find yourself working with only 1 or 2 libraries for a given project that might have used 20 or 30 were it written in python.
Why are there so few libraries?
In part because C++ is used for the kind of low-level systems where libraries aren't that useful, because of how specific the software is and how important performance is.
In part because...
iv - Package managers and build systems
Not only does C++ not have an official package manager, it doesn't even have a build system.
Various wannabe package managers exist, but as of 2018, my take was that none of them was popular enough to be useful.
Happily enough, most libraries are rather old and popular, so you can actually install them by installing the {library_name}-dev
package for your operating system (project-based versioning? static binaries? huh, what was that? I didn't quite hear you over the sound of saving 20 whole KBs of RAM by dynamically linking).
Build systems also abound, but at least there are two de-facto standards. Namely make
and cmake
. The role of cmake
is to generate makefiles, so in that way, it can be seen as an abstraction overmake
.
Overall I suggest trying to:
- Learn the basics of
make
, enough to compile a static binary for a hello-world using 2 different files. - Learn the basics of
cmake
, enough to build a simple library that can be compiled to link both statically and dynamically using a single "lightweight" dependency (e.g. crow) - Try to compile a few large projects from source (recommendation: clickhouse, pytorch, mariadb)
Again, I'm sure you'll be delighted to know that in-house package managers and build systems are plenty, and to some extent, you're best off learning the tools your team is using after you've got a hang of the basics.
When you've reached the end of the line trying to do things "the correct way", google LD_LIBRARY_PATH
.
v - Expertise
So, now you've read 1 or 2 books, you browsed cppreferences and stack overflow, you spent a hundred or so hours creating some simple standalone programs and libraries and did some hacking to get a hang of build systems and library management.
Where do you go next?
C++ is a language for specialization, it's a vast and very powerful toolkit, it shines when you try to solve hard tasks with it.
Ideally, you already have a task at hand and can specialize in that. But you might want to branch out, or your workplace might be quite bad at explaining what it needs of you.
Here are a few ideas for things you can dig into in order to get a feel for how C++ is used in the "real world":
Learn low-level memory management. The kind where you write allocators and think of code from a cache-centric perspective. This book is a very good intro to hardware that you'll need as a primer, then you should learn more about CPU caches. Specialization bonus: from now on you will forever get to be a smartass when talking about performance with anyone except other tryhards like yourself.
Concurrency and parallelism are a fairly good thing to know about in general. And learning how to do them right in C++ translates into knowing how to do them right in many languages. I recommend starting with this book; Then either going down the multi-machine path which blends into the networking and shared mem side of things, or looking at coroutines and other ways of making single-machine concurrency even more efficient. Specialization bonus: You can now sneer at the concurrency primitives of all other popular languages as inferior abstractions that sacrifice speed and elegance for ease of usage.
Lock-free data structures, which are very niche, but they are a way to really get up-close and personal with memory ordering, which you will read about when learning how to do concurrency but then never use. They are also amazing brain teasers if you enjoy puzzles. Start with everything Preshing has on the subject. Specialization bonus: You are now vaguely annoyed that lock-free data structures aren't present in every standard library.
"Systems programming", meaning anything that's big and complex and has loads of moving parts... or under the more academic definition: "making programs that serve as a platform and provide unified APIs for a variety of other programs to function together"... yeah, that doesn't help. In practice this means kernels, game engines, simulation engines and so on. There's nothing "special" about this, but it usually involves building pieces of software that are very complex, very safe and very efficient, so you end up with extremely different design patterns than in most other places. A good starting place, I think, is Robert Love's book about how Linux (the kernel) works. Specialization bonus: You are now able to see that arch and gentoo are comfortable weakness resulting from corrupt modernity, you switch to using Linux From Scratch until you're done building your own OS.
Metaprogramming involves understanding the aforementioned template system of C++ to a T, with some macros and other compile-time abstractions (e.g.
constexpr
andauto
) added in. This is very difficult and I don't know how to do it, I gave up after I read some code that did iteration via recursion at compile time. Specialization bonus: You can buy a very thick and famous book that nobody understood, display it prominently on your desk and tell your colleagues you know metaprogramming; Don't worry, they don't know it either so they'll never figure it out. Everyone will be impressed.Learning how to use GPU-related libraries/languages. The top picks here are probably Vulkan and CUDA. This is a fairly hot area right now due to
, so it might have some practical benefits too. Specialization bonus: You now work for Nvidia, which means you can get last-gen GPUs the day they are released even during peaks of the bitcoin hype cycle.
vi - Don't learn C++
I've mentioned "company you work at" here a bunch of time and for good reason, I don't think there's a lot of incentive to learn C++ unless you need it for your job.
If you need a language made for performance Rust is basically just as fast, with a lot of added safety and quality of life features, much better docs, and one of the best package managers and build system in the world.
If you want to work in the "low level" space then C is still the dominant language and Rust is the fastest growing in popularity.
If you want to learn it for scholarly reasons, then C is a much easier alternative.
It's a very interesting language and learning it will serve as a crash course for understanding many different things throughout computer science and software engineer. But you can probably learn those things in other ways that are less time consuming and infuriating.
I don't think C++ is going to die anytime soon, but I think there's a high probability that it will go the way of Java in becoming relegated to mostly legacy projects with greenfield stuff either choosing to use Rust or picking a higher-level language since performance is less of an issue nowadays and compilers have gotten much better at optimizing even laughably inefficient languages like python or ruby.
A lot of the projects it's going to be "relegated" to are fucking awesome, I would give an arm and a leg to work on some of them, they include names like pytorch, tensorflow, scylla and clickhouse. But learning it is a huge time investment, and getting hired at most awesome projects is very difficult (at least on any decently paid positions).
If you have your mind set on learning C++, no matter the reason, I do hope you find this guide a helpful start.
Published on: 1970-01-01