Modern C++ for Python people
This is a quick-as-possible guide for Python people wanting to get their feet wet in the land of modern C++. Obviously I’ll skip a lot of detail — my primary aim is to send you in the right direction, and show you that modern C++ is not as hard as you might’ve thought. Let’s go!
Get going
Honest to God, just use XCode. Go File, New Project, Command Line Tool and it’ll set up all the scaffolding and stuff for you. Visual Studio I’m sure does something similar — just make sure you use and IDE that has all the build stuff built in because building C++ projects can be a pain in the arse.
Spin up a new project, press the “play” button in the top left corner — voila. You may need to show the “debug area”, use the middle one of the three buttons top right. The debugger works the same as (eg) PyCharm — click in the margin for the line of code you want to stop at, press play, done.
Syntax
C++ uses curly braces to denote blocks of code and semicolons at the end of lines (but not blocks). Tabbing is the same as Python but has no actual meaning. Comments are // where you would use # in Python.
Huge fundamental difference part 1 of 2
C++ is a static language. The crux of this is that the type of a variable needs to be declared before you can use it — for instance:
int i;Declares an integer called i. Not exactly rocket science. In cases where it should be able to work it out for itself, use the word auto.
auto i=7;If it’s ambiguous the compiler will have no problem letting you know.
Collections also need to contain specific types, and the types they hold form part of the type of the collection itself. For instance:
std::map<std::string, std::string> like_a_dictionary;Creates a dictionary with string keys to string values, and the variable like_a_dictionary has type std::map<std::string, std::string>.
Huge fundamental difference part 2 of 2
C++ ‘modules’ are written with two files called the header and the implementation. The header is a statement of what is in the implementation and how you connect to it — the purpose of this being that you can now connect to a binary only C++ ‘module’ without needing the source.
You import these headers with the #include directive that works pretty much the same as import in Python except that there is slightly different syntax if you’re importing a system library:
#include <map>as opposed to something that is part of your project:
#include “something_i_made.h”The other big difference is that a lot of the ‘builtins’ like strings, maps etc. need to be explicitly included before you can use them.
Getting stuff on screen
The C++ standard library (that lives in namespace ‘std’) exposes an object called std::cout that is stream 1 in unix terms. You write a pipeline like this:
std::cout << “Hello World!” << std::endl;You send format instructions down the pipe also (hence endl meaning ‘end line’), and C++ will work out all the type conversions for you. Note that your boilerplate will contain a \n, this is bad form, don’t do this.
The string format functions are a pain in the arse and for any non-trivial templating you’re going to need a proper formatting library.
Strings
C++ strings work much as you might’ve hoped.
Remember to #include <string> then you can do things like:
std::string one=”one”;
std::string two=”two”;
std::string both=one + “ “ + two;
std::cout << both << std::endl;Slices are made with .substr
Containers
Much like python you can implement many patterns using the basic vector (like Python’s lists). You can call .front and .back like a list, and call .push_back (append) and .pop_back like a stack;
Similarly there is a map that provides the familiar [] operator:
std::map<std::string, std::string> mymap;
mymap[“dave”]=”oranges”;
mymap[“fred”]=”apples”;
std::cout << mymap[“fred”] << std::endl;There are variants of the above — a proper list, a priority queue, a set etc.
Iterating
You do a ‘for .. in ..’ like this:
std::vector<std::string> names;
names.push_back(“Alice”);
names.push_back(“Bob”);
for (auto name: names) {
std::cout << name << std::endl;
}Classes
The static nature of C++ means that the exact content of a class needs to be defined at compile time and can’t just be extended with self.this=that. C++ classes are a lot like Python data classes…
class example
{
public:
example(int initialise=0) : prop(initialise) {};
int prop_plus_one() { return prop+1; };
private:
int prop;
}Things to note here:
- C++ does not use
__to indicate that something should be regarded as private and instead has explicit public and private definitions. - The method with the same name as the class is the “constructor” and performs the same role as
__init__. - Properties are initialised with an initialiser list (following the colon), not with a collection of
self.prop=initialisecalls. - C++ has a
selfand it’s calledthis. In most cases (likeprop_plus_one) you don’t need to use it. - Just like Python, C++ can pass default values to methods.
Also, building the entire class in just once place — as above — is not generally the way things are done (and is done that way here for brevity).
Garbage collection
Contrary to popular belief, garbage collection in C++ is really easy. In essence, when an object falls out of scope, it (and anything it refers to) are garbage collected. In the std::vector example above, the vector, the strings it holds, and the temporary name are all cleaned up automatically.
There are hoops to jump through when working with ‘legacy’ C++ and C itself but for modern C++ this is a done deal.
Batteries not included
Unlike Python, the C++ standard library really does not cover much ground aside from supporting the language. Also unlike Python there is no pypi and the situation around module packaging is really dire. Common sources of extra functionality are:
- C libraries, which C++ can access natively. The C library environment is generally called “an operating system”, and when you run (for example)
apt install libbluetooth3you are installing the binary library; and runningapt install libbluetooth3-devinstalls the files such that both C and C++ can access this library using#include <bluetooth.h>. - The Boost libraries are extremely common in C++ projects and almost act as a ‘feeder’ into the standard library. As a result, care should be taken to not use a boost equivalent for something that is now part of std.
- Various curated lists.
Do it!
None of the above involved any pointer arithmetic, had any opportunity for buffer overruns and will not leak memory. Unlike Python, no environment needs to be installed on a client machine and glue code onto C is non-existent.
And it’s fast. Oh God yes it’s fast.
C++ has moved on, give it a go.
