LearnCPP: Website devoted to teaching you how to program in C++
learncpp.com
learncpp.com
I also find it very interesting to look at the pedagogy of these sites. In the case of this site, it starts with a lot of history and computing. This is common for books, but asking a new user to wade through so much preamble before any 'meat' is asking a lot. In the first part where code is shown/explained:
https://www.learncpp.com/cpp-tutorial/statements-and-the-str...
is a lot of upfront jargon for a newbie to process. ('pre-processor directive')
It does do a good job of showing how to set up visual studio. However these days, a htttp://repl.it is surely a MUCH easier way to get up and running.
I wrote a very small ultra-beginner guide for a young relative to learn C. It gets right into what C code looks like, makes connections to the math they have seen in school, and tries to hold back terms until they are really needed (omitting details where needed)
It isn't polished designed for widespread use, but I think for the truest beginners its better than other guides I found on the web.
Then I began to study algorithms and then code generation at the assembly level. I've written very little assembly. But I want to generate assembly. This puts me in a difficult position.
Today I think C++ is fascinating as a language because it has wide implementer support (cppfront, MSVC, GCC, clang) and it is well defined as a language.
Someone can read the C++ standard documentation and implement a compiler for generating assembly for that AST. That's fascinating. Especially for a language as advanced as C++.
I am also fascinated by metaprogramming and C++ templates. I needed to learn how to use C++ templates to use coroutines with threadpools in C++. Can't say I understand them completely but I understand how we need to provide specializations to the compiler so it knows how to generate code for different cases.
I feel there's a missing orthogonal specification of computation that is cleanly compilable. As with Rust, with C++ there is many programs that are wrong by arrangement of tokens. It would be better if most arrangement of tokens are valid programs, due to semantics of the language not being subtle.
https://stackoverflow.com/questions/74520133/how-can-i-pass-...
I feel there's an omitted abstractions when it comes to code generation. The languages we use to represent computation in and relationships between things are rather low level. Mutable state is very difficult to reason about.
https://cplusplus.com/doc/tutorial/
It's way less verbose and more to the point.
Just as an example, cppreference doesn't have a page dedicated to std::string (when you search for it on Google, it tkes you to std::basic_string) whereas cplusplus does.
Even comparing the two pages, cplusplus immediately gets to the point that std::string is just a std::basic_string<char>, whereas cppreference has three paragraphs of technical minutiae before it finally points out what std::string is.
Even though cplusplus is out of date and incomplete, it's still often more useful than cppreference when you're trying to get your head around STL for the first time.
Sure you'll learn some C++ syntax, but you'll learn the C++ from 20 years ago, not the modern C++ with smart pointers and all that stuff which is basically turning it into a new language.
This was my main resource and can highly recommend.
I still wish it had better navigation design, like a side bar for easy access to the ToC, or a drop-down menu for the same thing. I have to use the back|forward to do that.
cplusplus.com is out of date, but it has the simplest and easiest web interface to me comparing to either learncpp.com or cppreference.com, super easy and simple to navigate: https://cplusplus.com/doc/tutorial/
I don't even know what I would recommend to a newbie. I learned C 25 years ago, and dabbled in C++ 2 or 3 times since then.
Bjarne's books might be great, but they aren't for anyone new to C++ and especially not anyone new to programming in general. C++ For Dummies/21 Days style books are just bad. And there are more bad websites than I can count.
C++ is awful for beginners exactly because of undefined behavior, no good book can fix that, IMHO.
As for topics covered, talking in details about linkage, functions, constexpr, bit manipulation before if/for statements is, uhm, questionable, if this is aimed at beginners. Then the site talks about type conversions, function overloading, structs, and arrays only appear somewhere in the middle. Moreover, much simpler std::vector is introduced _after_ C-style arrays. Wild ride for a reader, but one can argue such order is more "academic", whatever that means.
I disagree. Not sure why PPP[1] wouldn't fit the bill. It's specifically geared to people who haven't programmed before.
It's just not a clear, step-by-step introduction.
I regularly see ads searching for C++ developers. I'm in an automotive-heavy region in Northern Europe. C++ is widely used in HMIs, AD/ADAS, and general service development (diagnostic services, middleware). I also see the need of C++ developers in medtech and automation companies around here.
The ads request some experience, but in practice they are happy to recruit what they can find.
Some technologies change, so does C++, but not so long ago I landed a C++ gig for €80+/hr, although being more of a ANSI C90 expert, only used C++ occassionally (for test environments mostly), and being completely out of synch with the "latest" concepts of modern C++ and its tooling (as a reference, std::move was new to me; CMake was an annoying bigger sibling of Make). Customer was happy until that Chinese virus became a fad.
There was an old joke about everyone using a different subset of C++ but like most jokes it's mostly an over exaggeration.
C++ (and C) have amazing backwards compatibility and there is a strong chance that code written 30 years ago will still compile, link, and run as long as the dependencies haven't also changed too much (I'm looking at you Win32, X11, Motif). That gives you the time to migrate code bases over time without the fear of being left behind and unsupported.
Even if, for some reason, you were writing C++98 for the last 30 years, it shouldn't be too difficult to make the jump to newer standards. The biggest change, in my opinion, is lambdas and move semantics, and it's not to difficult to apply those to an old code base (if you want to) and start modernizing it. Some people say C++20/23 is a new language but the fundamentals of C++ haven't changed too much and I'd say it's easier to learn C++23 coming from C++98 than it is to learn Rust coming from C++98.
I generally advise people wishing to learn C++ to read Bjarne Stroustup's 2nd Edition of The C++ Programming Language (TC++PL) first. All the Basic language features are there and it is manageable (i.e. C++98). Once they have an idea of this subset they can then move on to later standards eg. TC++PL 4th edition for C++11 and A Tour of C++ 3rd edition for upto C++20. This demonstrates the evolution of the language and brings home the point that there are orders of magnitude more C++98 code then C++11 and later.
> When an initializer is provided after an equals sign, this is called copy
> initialization. Copy initialization was inherited from the C language.
>
> int width = 5; // copy initialization of value 5 into variable width
>
That's not quite right. Consider the following program:
#include <iostream>
struct A {
A (const A& other) : x{other.x} { std::cout << "Copy ctor\n" ;}
A (A&& other) : x{other.x} { std::cout << "Move ctor\n" ;}
A() : x{0} { std::cout << "Default ctor\n" ;}
A(int x_) : x{x_} { std::cout << "int ctor\n" ;}
A& operator=(const A& other) { x = other.x; std::cout << "Copy assignment\n" ; return *this; }
A& operator=(A&& other) { x = other.x; std::cout << "Move assignment\n" ; return *this; }
int x;
};
int main() { A a1 = A(5); }
The constructor used here will not be the copy constructor. There will be just a single construction, of a1, and it will be the "int ctor", i.e. `A(int x_)`.See it on GodBolt : https://godbolt.org/z/eT8soWMxE
I don't know if this characterizes other parts of LearnCPP, haven't gone through it myself.
https://en.cppreference.com/w/cpp/language/copy_initializati...
So I half-take-back my comment.
I’m thinking something like MIT’s “missing semester” course which teaches the boots on the ground part of software like how to use Git.
https://missing.csail.mit.edu/
Maybe these resources exist for C++ and I just never found them.
I think a lot of “modern” languages get this right by including these things from the start. The experience is so much better.
I don't know how others did it, but I learned with MS Visual C++ in 1996.
File -> New Project -> press F7 to compile, F5 to debug. That's it. ~30 years ago they got it right. I even remember my Windows CE experience ~15 years ago that allowed to build and debug the entire OS from an IDE.
Now you have to open your command line and write like it's 1985.
Today VS is free (Visual Studio Express?), with analyzers, tests, vcpkg, etc. There is also Qt and other similar tools that I use for embedded like Keil, IAR, Eclipse derivates, etc.
C++ != Makefiles. I don't write Makefiles or fiddle with the build system since... ever?. Except for some AOSP stuff that still uses them or perhaps editing some linker script for embedded.
PS: that said, "experience" is relative. Having to use the command line in general but mostly for learning is terrible.
Yak shaving learning how to use all the compiler and linker flags, and library setup before writing any line of code.
Debugging vcproj files is as easy as going down the boilerplate generated by shell scripts and build generators.
In addition to building, it will show how to add cppcheck and clang-tidy to your cmake files. That part is pretty easy. Just don't turn on every check in clang-tidy. Many of them are for specific code bases. Modernization checks are my favorite ones. Keeps you doing stuff the modern way.
My link has you doing dependency management with git submodules. That is a method still in use and even advocated for, but conan is often touted as the more modern way to do it. I've used it on some teams, and I'm undecided. I also have no good resources for it.
Modern CMake should be using toolchain files to specify the toolchain/flags. That should be included in ever CMake intro. (Hacking those into your CMakeLists.txt is not okay)
gitsubmodules are also a hack
1: Many dependencies are not setup to be used as a CMake subdirectory. Variables such as the project-version-number get overwritten by the parent project and more dangerously the submodule can start to change variables in the overall project.
2: Dependencies will often reuse target names. For instance, libraries often have a target called `uninstall`. Because redeclaring a target in a different subdirectory is a no-no - CMake crashes
Proper dependency management can be done directly through CMake without repeating yourself by using Hunter: https://hunter.readthedocs.io/
This solved the diamond problem, gives you proper namespaces in CMake and with Polly you can have sane toolchain files (https://github.com/ruslo/polly - but you can also just write them manually). Everything is built on CMake and Git (and git hashes). You get nice dependency build caches and forking dependencies is also trivial
EDIT: The creator of Hunter has his own CMake Intro. I haven't gone through it while-learning, but it looks comprehensive and informative: https://cgold.readthedocs.io/en/latest/
this so much. I made a toolchain generator to make myself toolchains with common set of flags (asan, lto, etc specified with a single simple word on the command line for each "feature" or at worst a "key=value" pair, e.g. "compiler=gcc", "linker=lld") and really it made my life so much better: https://github.com/jcelerier/cninja
If the dependency you want to use has no dependencies of its own - then it can be used directly with no changes (as long it's CMakeLists.txt is sane and it can use a passed-in toolchain file)
https://hunter.readthedocs.io/en/latest/creating-new/create/...
If the dependency has its own dependencies, then you need to "Hunterize" it - specify library versions, tweak the targets to use namespaces, etc. They're usually small changes. They have a huge list of Hunterized forks:
https://hunter.readthedocs.io/en/latest/packages.html
Finally, a CMakeLists.txt that's been made to work with Hunter can always revert back and be run without Hunter. So the change isn't intrusive. https://hunter.readthedocs.io/en/latest/overview/compatibili...
A minimal CMakelists.txt will look something like:
HunterGate(
URL "https://github.com/cpp-pm/hunter/archive/v0.23.297.tar.gz"
SHA1 "3319fe6a3b08090df7df98dee75134d68e2ef5a3"
)
project(Foo)
hunter_add_package(Boost COMPONENTS regex system filesystem)
find_package(Boost CONFIG REQUIRED regex system filesystem)
add_executable(foo foo.cpp)
target_link_libraries(foo PUBLIC Boost::regex Boost::system Boost::filesystem)
The first block specifies the available package list (you can fork and host your own). If you disable Hunter this isn't usedThe line that reads `hunter_add_package` is the Hunter part that downloads and build the dependency (using the current toolchain file). But if you disable Hunter then that line would simply get skipped.
In the third line `find_package` will run.. and if you had Hunter build the dependency then it'd use that as the target - otherwise it just runs like "normal CMake" and it tries to find the package elsewhere (like from your system package manager or whatever)
If your dependency has its own dependencies as git submodules.. then I'm not super sure you have a very clean migration path b/c they will not be using `find_package` and will instead be using `add_subdirectory`. Maybe you could patch their CMakeLists.txt to use Hunter when explicitely enabled, and then drop down to `add_subdirectory` otherwise. It'd be a bit ugly but they would keep their workflow I guess. You'd need to check that their targets end up with the same namespaced names (with the :: notation) when seen from your project... I don't know off the top of my head how Hunter handles a subdirectory with a project name of it's own
I don't see any reason that wouldn't work - but.. you'd have to test it. I've never tried running a Hunterless top-level project with a Hunter-ized subdirectory. The top level project would still get some benefits like the namespaced targets (so you won't clobber anything in top-level)
The only small catch is that Hunter inevitably does build a cache of build artifacts/targets for your dependencies. As long as you keep using the same toolchain files these keep getting reused each time you rebuild your project. That does however mean you will get some user folder like ~/.hunter with those build artifacts (look at the Hunter config options.. maybe this can be somehow hidden in the build directory?). I dunno if that would irritate the project users. If it's company internal that's probably an okay ask. If it's random devs on github then that's a bit not-nice :)
I would recommend any other C++ build tools that use a proper programming language for scripting, be it Meson or Bazel.
I would think that rules like https://github.com/liuliu/rules_cuda should work for you in Bazel. (Tensorflow also uses Bazel, so I don't think that this should be a problem.)
Some ideas for a curriculum:
Context
- C++ as a standard, compilers as implementations
- a build tool's role in handling compilation and linking
- compilers having limited abilities, having limited warnings and analysis by default
Build tools
- evolution: e.g. make -> autotools, cmake, meson
- focus on meson as the build tool of choice (personally I'd avoid CMake since it has a lot of legacy baggage)
Testing
- gtest/gmock
- catch
- designing for testing
Analysis tools
- why you should care: security, catching bugs
- cranking up built-in compiler warnings to reasonable standards
- external tools like clang-tidy, cppcheck
- sanitizers: address sanitizer, leak, thread, etc.
- fuzzing
Dependency management (probably the toughest, since it's still a mess)
- history: usually just relying on system packages, or installing libraries globally from source
- Conan (probably the best option for simple dependencies that's actually catching on)
- CMake external projects, Git submodules
- Docker
- Nix (if you're feeling adventurous)
In france when I started engineering school (early 2010s) we had classes about:
- using the shell, emacs, being at least basically proficient unix tools
- using make, cmake, configuring compilers etc
wild that it isn't more common, this explains a lot!
One can say "but that's how I learned, and I am fine and shine today". This is probably true, but then I believe that such a person had the right background to anyway learn by themselves. I see our mission as teachers to help the students that actually need the help, rather than letting them give up too early, in favor of some kind of excellence evolution. And I believe that if we prepare the right groundwork (explaining all the ropes before we start pulling them), then even the more advanced students will be able to learn even more that they would by themselves in a more struggling environment.
Sure it is easier for simple projects, but C++ is not for simple projects.
1 https://cmake.org/cmake/help/latest/module/ExternalProject.h...
I agree and that would be great. I'd also love a place to learn design with feedback. Should I use a friend function? Free function? Separate class? Abstract class? Should I create a separate folder and start a module?
It would be great to have something where you try an implementation, get feedback, and try again maybe a few times and then are presented with a few ideal options that you might not have tried.
C++ is a no thrills language which lets you have freedom but freedom to also shoot yourself in the foot 100+n ways, but this gives you a good foundation as a developer IMHO.
Every time I think about garbage collection in Java, I can appreciate that I am not having to write code to destruct an object or worry about passing references incorrectly.
https://stackoverflow.com/q/147130/1593077
and my particular answer:
https://stackoverflow.com/a/48046118/1593077
in essence, with Modern C++, it is relatively easy to just not produce garbage which needs to be collected :-)
In fact, the most striking thing coming from a language like Java or C# isn't memory management at all, is how utterly non-OO C++ actually is, especially the standard library. I understand how key the zero-cost tenet is in C++, but it's very alien to be picturing an interface and thinking you'd like an Iterable<char> or IEnumerable<char> there, but having to learn about iterators and traits and concepts etc. To be honest, there are equally many functional affordances in C++ as OO ones at this point, but the native core is generic programming, which is very idiosyncratic.
You could definitely (?) implement a Java-like container framework, with class like Iterable<char> or IEnumerable<char> and almsot every OO bell and whistle - if you wanted to. But it would not be very useful.
As much as I like modern C++, use after free is still way too easy to commit. But if you stick to value types and mostly don't store references/non-owning raw pointers, then it's OK.
Is it not the way?
Two words: undefined behavior. In other languages, if you do a mistake, something fails around the place where you did it, or at least afterwards, or at least you can reason why the failure is exactly where it is. In C++, you cannot. Accidental array bounds overflow? Too bad, now your program crashes in a completely unrelated closing bracket (not even a statement) five minutes later.
In other languages, if your program does not crash and produces a correct answer until point X, you can be more or less sure that everything afterwards at least gets corrects inputs. Not in C or C++: if there was an UB before point X, the program may look like it does random things: some stuff is printing, some stuff is shown in the debugger, random lines are executed, arithmetic operations make no sense, perfectly valid functions crash: https://stackoverflow.com/questions/54120862/does-the-c-stan...
I learned C++ as an absolute beginner in school back when most memory debugging tools didn’t even exist. Undefined behavior was just another bug that one learned to fix and most of the time it was nothing more exciting than a crash. Being disciplined avoided the problem in the first place…
People really have a tendency to dramatize C++. Yes, memory errors are a significant problem for people writing operating systems or browsers that get attacked all the time. For a beginner C++ can be much more fun and instructive than any so-called safe alternative.
C++ is fun for sure, it was (and is) fun for me, but it's a very specific kind of fun.
If a beginner started off with a clang or gcc toolchain, then I would immediately suggest the following command line options for the compiler (the exact standard version does not matter, just stick to one):
-std=c++20 -pedantic-errors -Wall -Wextra -fsanitize=address,undefined
And there are a few toolchain specific macros worth adding.This would help with most undefined behaviors encountered as a beginner, although the sanitizers don't catch everything.
Absolutely do use -Werror on CI, where nobody even looks at logs of a passing pipeline.
Without -Werror you can see all your warnings at once, for better or worse.
Plus rusts strict memory management rules don't really translate to other languages, and c++ has a habit of changing wildly. The c++ of 10 years ago barely looks the same whereas python and c# feel less like the goalposts are moving.
Java seems interesting from an employment perspective, but the small stuff I've touched seems extremely verbose. I feel like I have to write and think way more to do simple stuff. But I just had a brief introduction, I guess I can get used to it.
I wanted a compiled language that allows me to tackle some interests I have, and I feel It will be c/c++ wether I like or not, because one of my interests is fiddling with hardware. Nim can compile down do C apparently but it isn't widely adopted.
I'd suggest waiting until you learn some java/c# before starting on c/c++, or instead starting at old school c (k&r c) or arduino c++. Modern c++ is a beast to learn.
C++ is one of those languages that people write anything and everything in. Whatever you need, whatever you’re curious about, it’s likely out there.
As for what it feels like, if you want safe but boring, go with Rust. If you want exciting go with C++.
Personally I’d never start with Rust, it’s like biking everywhere with training wheels.
Rust will beat you over the head with a way of thinking that carries nicely back to C++, and the tooling (Cargo, etc) is more comparable to what someone coming from another language ecosystem would know. Smaller things like Rust's decent support for functional programming seems to click with everyone I know who's dabbling from the JS world.
For those reasons I'm very excited about Austral. The borrows, linear types, and the notion that anything that isn't explicit is wrong, all appeal to me.
Doesnt seem like it needs to be