Different people have different ideas of what is simple.

— Bjarne Stroustrup

Contents

Versions

Cpp variants

As C was apparently not Good Enough, C++ developers lack the temperament to leave things well-enough alone. They’re constantly re-imagining the language as broken and trying to fix it. Every couple of years there is a major change in how things are done.

Wikipedia’s enumeration of C++ versions is ok. Here is a list of more exotic species. Here is a whole history of the genus. Here is my little catalog.

C++98

AKA - ISO/IEC 14882:1998

Main Features
  • RTTI (dynamic_cast typeid)

  • covariant return types

  • cast operators

  • mutable

  • bool

  • declarations in conditions

  • template instantiations

  • member templates

  • export

Library Features
  • locales

  • bitset

  • valarray

  • auto_ptr (now deprecated)

  • templatized string

  • iostream

  • complex

Standard Library Features
  • algorithms

  • iterators

  • function objects

C++03

AKA - ISO/IEC 14882:2003

Mostly bug fixes and subtle implementation standardization details.

Features
  • Value initialization

C++11

  • AKA - ISO/IEC 14882:2011

  • AKA - C++0x

C++14

AKA
  • ISO/IEC 14882:2014

  • C++1y

Descriptions
Main Features
  • Function return type deduction

  • Alternate type deduction on declaration[5]

  • Relaxed constexpr restrictions

  • Variable templates

  • Aggregate member initialization

  • Binary literals

  • Digit separators

  • Generic lambdas

  • Lambda capture expressions

Standard Library Features
  • Shared mutexes and locking

  • Heterogeneous lookup in associative containers

  • Standard user-defined literals

  • Tuple addressing via type

  • Smaller library features

C++17

Published: 2017-12-01

Here is the latest official C++ 2017 Standard - 1622 pages!

AKA
  • ISO/IEC 14882:2017

  • C++1z

C++20

As one might expect, this one is still being worked on in 2019.

Features

File Extensions

What should we call our files containing C++ code?

  • foo.c - Classic unplusplused C. Nice and simple.

  • foo.c++ - It’s been tried, but no. Never do this.

  • foo.C - Popular in the early days with Unix people — which of course means: not popular.

  • foo.cc - I started with this and it seems fine. Short and clear. But it has slipped into relative obscurity. That’s fine but I’m more concerned with confusion over variables like $(CC) (from make) that do not have anything to do with C++. In make, "CC" is "C Compiler" or possibly "Compiler Collection" depending on your historical period.

  • foo.cpp - This is the obvious choice for the majority of people because it is the common preference of a popular tool chain in a regrettable OS. I have used this convention even though impoverished OSes do not concern me. But a better reason to avoid it might be the confusion with make variables like $(CPP) which also has nothing to do with C++; that stands for "C Pre Processor" and I think that is fair to respect and avoid any confusion with.

  • foo.cxx - That leaves this weird one. I previously avoided it as contrived, cutesy, and unnecessary, however make variables once again provide clear guidance. The variable $(CXX) is the variable for the C++ compiler, defaulting to g++. With that in mind this seems like the clear choice.

  • foo.h - Unless the header contains specific C++ syntax, I’d continue to use this for headers. Normally foo.hpp is seen in the wild but foo.hxx seems valid too.

Preprocessor

Tag brackets mean look for this file in the directory where all the standard libraries are stored.

#include <iostream>

Double quotes mean the same as tag brackets or the current directory if the specified file is found in it.

#include "main.hpp"

Namespace

The following line is an example of how kludgey C++ can be:

using namespace std;

I find this command to be awkward. It is cryptic, not part of your train of thought when trying to get something to work and, unfortunately, hardly ever unnecessary. This line simply must be included to activate the correct name space for certain important libraries. There may be others but <iostream> and <string> are definitely some that need this command.

Without it you need something like this.

std::cout<<"This is suboptimal.";

Although this is an annoying requirement because most of the time it is used mechanically in the case shown above, the namespace mechanism is a C++ feature that allows better organization and protection of program elements.

Starting with C++2011 the using keyword can have a different meaning. It is used to set an "alias". As far as I can tell this works much like a typedef. Maybe something like this.

typedef std::map<std::string,int> mymaptype;
using mymaptype= std::map<std::string,int>; // Same thing basically.

Apparently it’s better to go with the second, newer, style. One reason is that typedef doesn’t handle templatization well. There may be other reasons but it is at least good to know what you’re looking at when you find code like this.

Comment Styling

In C, the comments are this bizarre syntax:

/* This is a classic C style comment. */

In C++ that is acceptable but there is another style that has a starting designator and runs to the end of the line. Like this:

// This is a C++ comment.
x++ // The beginning of this line is not a comment but this is.

Style

For style tips in general, you could do worse than to emulate these guys. (Do they not host it themselves anymore?)

Here’s another.

Note that OpenCV also has a style guide. They prefer names ending in .cpp and .hpp. And 4 spaces, no tabs.

Variable Types

As with C, all variables must be explicitly declared before using. The point of this relates to C and C++ and their very explicit use of memory management. Note the acronym RAII stands for Resource Acquisition Is Initialization. RAII guarantees that objects are ready to go if they’ve been initialized. I think this is in contrast to C’s ability to make pointers to hypothetical things that may want a lot of resources later but come up short.

Constants

Like C, make a variable immutable with the const keyword. Hmm, a "read-only variable", like the C++ error messages say, is an oxymoron, right? Still, it is a part of the C++ religion to pray to the const gods at every opportunity.

This is simple in the simple cases. But there is all kinds of mischief that can arise from this. The most absurd to me is the mutable keyword which can make const declarations, uh, less const.

Wait a moment… This just in… I’ve received word that C++11 has introduced a new keyword into the language — don’t act all surprised — the word is constexpr. As far as I can tell, const can be assigned a value (that thence remains constant) at runtime, but constexpr is carved in stone at compile time. I would imagine that things like this are a teensy bit more resource efficient.

constexpr double PI= 3.14159265358979323846;

The normal const could be applied to things like this.

int main(const int argc, char** argv){  ...

Here the number of arguments can be different depending on how the program is executed, but once the value is set, argc will be locked for the duration of the execution.

It turns out that constexpr can be used with functions too. This is limited to simply return (maybe with some awful ternary operator tricks). But C++14 expands the potential of constexpr functions. I’m thinking of these like old C preprocessor macros that do simple things during compilation so that the precomputed answers are injected into to the source code. But C++ tries hard to bring that sort of thing into the language proper. The limitation with constexpr functions is that all arguments must also be constexpr for it to be effective. If they are not, it just pushes it out to normal runtime execution. Another fact to understand that helps explain it, is that such pre-computations at compile time will likely make the compiling process take longer.

There is also a C++ specifier called volatile which can be used in very rare situations where you explicitly want the compiler to refrain from performing any optimizations on this "special" memory’s operations.

Type Details

Note
Actually in some situations the Cpp11 auto keyword (not to be confused with the K&R C auto compiler hinting) allows the types of variables to be automatically deduced from context. Some more information and examples.

bool Exclusive to C++!

Boolean

1byte

keywords true or false, or integers 1 or 0

char

Character or small integer.

1byte

signed: -128 to 127 unsigned: 0 to 255

short int (short)

Short Integer.

2bytes

signed: -32768 to 32767 unsigned: 0 to 65535

int

Integer.

4bytes

signed: -2147483648 to 2147483647 unsigned: 0 to 4294967295

long int (long)

Long integer.

4bytes

signed: -2147483648 to 2147483647 unsigned: 0 to 4294967295

float

Floating point number.

4bytes

+/- 3.4e +/- 38 (\~7 digits)

double

Double precision float

8bytes

+/- 1.7e +/- 308 (\~15 digits)

long double

Long double float.

8bytes

+/- 1.7e +/- 308 (\~15 digits)

wchar_t

Wide character.

2 / 4 bytes

1 wide character

Note that C++ is more strict about type casting than C.

Variable definitions in C generally must be at the beginning of a block whereas in C++ they can be anywhere in the block.

C++ provides a way to get a runtime check of what kind of type a variable is. This is done with the typedef function and is useful when variables can be any of several types or objects.

Enum

C enum values are always sized int whereas in C++ they are a distinct type and can have different sized values. This defines a new user type DOW.

enum DOW {Sun,Mon,Tue,Wed,Thu,Fri,Sat};

You can do a lot in the definition. Here the type declares a variable (casual) and sets it.

enum DOW {Sun,Mon,Tue,Wed,Thu,Fri,Sat} casual=Fri;

Some people believe that enums should be named as singular nouns and not plural. Although enums may define a collection of possibilities for, say, problem_types, the possibility will just be a problem_type when actually used.

Enum Scoping

In the old C++98 days if you defined an enum and then wanted to use one of its member’s names for something else, that was a problem. For example if you had already defined a DOW enum as above, and then wanted this, that would lead to confusion.

auto Wed= Wedding();

The solution is to create a "class enum" or, as it is known by its less obvious but more correct name, "scoped enum".

enum class DOW {Sun,Mon,Tue,Wed,Thu,Fri,Sat};

Now you can have a star named Sun which won’t get confused with the day of the week enum member. Of course you need to refer to the enum with something like sleep_in(DOW::Sun) to prevent naming conflicts.

Literals

I was astounded to see some time calculations in C++ (14+) that involved numbers with time units, stuff like 8m+43s. This is accomplished with the std::literals namespace.

Note the fun and confusion that could arise from something like this.

x= 10s   // std::literals::chrono ten seconds
y= "10"s // std::literals::string the string - one, zero.

Oh, and don’t get confused by pair.second which is the second member variable (not function) of a pair or map.

This is part of C++11’s user-defined literals. They’re really not too far different from things like 0xCEl (a long) or 99u (an unsigned int). Let’s say you had an Altitude class and wanted to be able to set its object in feet, you might use something like this.

Altitude operator ""_ft(signed long n) { return Altitude{n, Altitude::FEET}; }

Then you could say stuff like.

auto tower= 50_ft
auto mountain1= 2732_ft + tower

I didn’t exactly check all of that but it is something like that.

Also note that C++14 started permitting the very continental European practice of sticking apostrophe’s where Americans put commas in long numbers. Apparently stuff like this is now legal.

constexpr auto USpop= 329'395'329;

Implicit Conversions

  • integer to float = OK

  • char to float = OK

  • float to int = OK (truncated obviously) John Carmack suggests to consider using rint().

  • float to char = silently does the wrong thing

Strings

Classic C Style - cstring

Because C++ is based on C, the spartan techniques of old school C work in C++ too. Note that as in C, double quotes signify strings and single quotes are characters.

#include <iostream>
using namespace std;
int main(){
    char my_char_array[4]= {'a', 'b', 'c','\0'};
    cout << my_char_array << endl;
    char unterminated_rubbish[3]= {'x', 'y', 'z'};
    cout << unterminated_rubbish << endl;
    char fixed_len_msg[]= "Really just an array of simple chars.";
    cout << fixed_len_msg << endl;
    return 0;
}

Note that in the example that unterminated_rubbish is just that. With no termination, functions like cout just keep reading memory until it finds a null. It can pick up all kinds of wacky stuff. In my example I found that it printed the abc string too until it found its termination byte.

abc
xyzabc
Really just an array of simple chars.

So think carefully about using this style of C character array strings with C++ functions. However the cstring library can be used with this kind of string and it does work fine if done carefully.

#include <iostream>
#include <cstring>
using namespace std;
int main(){
    char fixed_len_msg[13]= "Ok C string.";
    char msg_copy[13];
    strcpy(msg_copy,fixed_len_msg);
    cout << fixed_len_msg << endl;
    cout << strlen(fixed_len_msg) << endl;
    cout << strcmp(msg_copy,fixed_len_msg) << endl;
    cout << msg_copy << endl;
    cout << strcat(msg_copy,fixed_len_msg) << endl;
    cout << strcmp(msg_copy,fixed_len_msg) << endl; // <0 if A<B, >0 if A>B
    cout << *strchr(msg_copy,'C') << endl; // returns ptr to pos of char 'C'.
    cout << *strstr(msg_copy,"Ok") << endl; // returns ptr to pos of string "Ok".
    printf("The length is: %04d\n",strlen(msg_copy));
    return 0;
}

That code produced this output.

Ok C string.
12
0
Ok C string.
Ok C string.Ok C string.
-28
C
O
The length is: 0024

string Class

In C++ the string class is a more elaborate mechanism for working with strings. Strings are generally used like this:

#include <iostream>
#include <string>
using namespace std;
int main(){
    string mystring("Defined in constructor.");
    string somedots(4,'.');
    cout << mystring << endl;
    mystring= "Redefined by assignment.";
    cout << mystring << somedots << endl;
    cout << somedots + "and concatenation." << endl;
    cout << mystring.size() << endl;
    return 0;
}

Produces this.

Defined in constructor.
Redefined by assignment.....
....and concatenation.
24

Note that because it is a class (string) it can be initialized like a new object as an initialization function parameter. Subsequent redefinitions use the overloaded = operator to simulate the way normal people would expect a programming language to work.

  • S.length()

  • S.size() - seems identical to S.length()

  • S.empty() - 0 if not empty and a 1 (or maybe some other nonzero) when it is indeed empty.

  • S.clear() - force empty() to return true by erasing any previous content.

  • S.append("suffix") - A lot like +.

  • S.assign()

  • S.replace(change_position,change_length,replacement_string)

  • S.find(str2,pos) - Find the first occurrence of an entire second string’s position within string S. The pos parameter is to start looking only at or after a certain position; 0 is search all.

  • S.rfind() - Like find but finding the last occurrence. And pos is the maximum character to search. A value greater than or equal to S.length() searches the whole thing. "r" is reverse in these functions.

  • S.find_first_of() - Searches a string S for any characters supplied. Position limits are like find().

  • S.find_last_of() - Same as find_first_of() but the like rfind(). See rbegin() below.

  • S.find_first_not_of() - Invert the match checking of find_first_of.

  • S.find_last_not_of() - Inverted matching of find_last_of.

  • S.compare()

  • S.erase() - Erases particular characters specified by 1. position and length, 2. iterator position, or 3. starting and ending iterators.

  • S.back() - Access the last character.

  • S.push_back(char) - Append a character.

  • S.reserve() - Request a change in capacity. If you’re looking for how to reverse a string, see below.

  • S.substr(position,length) - Returns a new extracted string.

  • S.stTYPE - Type conversion functions where type is i (int), ui (unsigned), ll (long long), ull, f (float), d (double), ld

For find operations, if the target is not found, it will return string::npos which on my system produced 18446744073709551615 (2^64-1). Checking the return value for this is how you check if something was found.

Repeated Characters

Need a long line of dashes for something? Just create a string with an integer first argument. Here is some content between two lines of 20 dashes.

string(20,'-') << endl << "Content" << endl << string(20,'-')

Casting To Strings

There is a function called to_string(non_string) that makes strings out of many things, numbers mostly. One thing I found odd was that it did not seem to have a prototype that accepted char types. You’d think that would be pretty easy. But the answer to that riddle was just covered in the Repeated Characters section above. Just use string(1,mychar).

Truncating Strings

This is rumored to only work in C++11. Here is how to drop the end N characters in a string. For example, N=4 to get rid of the file extension such as ".txt" in a filename.

for (int i=0;i<N;i++) string_object.pop_back();

Reversing Strings

Or the equivalent to piping to the Unix rev command. Just define a new string with reverse iterators from the old one.

string backwards(x.rbegin(),x.rend());

Splitting Strings

To show a good example of strings in action, here is a C++ technique to achieve the functionality of Python’s split() function or the Unix cut command.

#include <iostream>
#include <sstream>
#include <vector>
using namespace std;
vector<string> split(string s,char sep){
    // Split string s on separator sep.
    vector<string> parts;
    string part;
    stringstream streamed_s;
    streamed_s.str(s);
    while (getline(streamed_s,part,sep)){
        parts.push_back(part);
    }
    return parts;
}
int main(int argc, char **argv){
    string teststring= "+11_0.22_-33_4.4";
    vector<string> nums;
    nums= split(teststring,'_');
    for (vector<string>::const_iterator i= nums.begin(); i != nums.end(); ++i)
        cout << *i << endl;
    return 0;
}

Replacing Strings

Here’s a pretty effective way to do simple string substitutions. This replaces globally in the string, not just first. You can also replace with "" and this works as a character deleter too.

string text_replace(string& s, const string& bad, const string& good){
    size_t p= 0;
    while( (p= s.find(bad, p)) != string::npos) {
        s.replace(p, bad.length(), good);
        p += good.length(); }
    return s; }
// Example use to get rid of evil tabs.
line= text_replace(line, "\t","    ");

Fancy Strings For People Using Weird Letters

Apparently C++11 introduced the char16_t which is a double byte char (the ordinary stuff a classic std::string is made of).

char     c{ 'a' };
char     cu8{ u8'a' }; // cu8 == c
wchar_t  wc{ L'a' };
char16_t c16{ u'a' };
char32_t c32{ U'a' };

Initialization and Definition

When I started programming with C++ in ancient times, if you wanted x to be 3 you said int x=3; sort of like you do with classic C. The problem with this in C++ is that it can be slightly ambiguous, or at least inconsistent. Note how I’m basically using a couple of ways to simply define things in the following code.

#include <iostream>
using namespace std;

class Fancy {
   public:
      Fancy(){x=0;}
      Fancy(int N){x=N;}
      Fancy operator=(int X) { x= X; return *this; }
   private:
      int x;
};

int main(){
    Fancy f(99);
    f= 33;
    Fancy g= Fancy(100);
    return 0;
}

Also note that if you tried to initialize a special type with an empty argument list like Fancy f(); you’d have basically just declared a function. Today with C++11 and beyond there is a thing called "uniform initialization". This uses braces and although it has its problems, it is a bit more consistent.

This would basically look like this:

Fancy h{101};

It can also be used to initialize more complex objects.

std::vector<int> v{9,8,7};

Input And Output

C uses scanf and printf for input and output. C++ can use these but idiomatic C++ programs use a different mechanism not available in C.

cin>>
cout<<

These are available from include #iostream. You probably also want to turn on using namespace std; to cut down on trivial scope chatter. These are really not exactly functions but more like named pipes (in the std namespace) which get data sent in and out of them (<< and >> are overloaded operators normally used for bit shifting).

The >> operator is the "extraction" operator and reads input "items" which are expected to be delimited by whitespace (space, newline, tab).

if (fileStream.is_open())
    while (fileStream.good()) {
        string word;
        fileStream >> word;
        // Do something with "word"
        }

Here is a complete output ("insertion" operator) example:

#include <string>
#include <iostream>
using namespace std;
int main () {
  string thestr("String objects can be output like so.");
  cout << thestr << endl;
  return 0;
}

The cout doesn’t just dump a \n; it also performs cout.flush().

Here are some good notes on C++ IO.

Standard Error - cerr

Sometimes you want normal output to go to the standard place, for example, a unix pipe, but you also want to generate some error messages and have them not go to the pipe. To write to /dev/stderr or stream 2 (I think) just use cerr << data << endl; just like you’d use cout.

cin and getline

It seems that cin is good for reading space delimited fields one field at a time (or something like that), but it doesn’t read whole lines.

#include <iostream>
#include <string>
int main() {
    std::string myLine;
    std::cout<<"Enter the whole line: ";
    std::getline(std::cin, myLine);
    std::cout<<"Your line is: "<<myLine<<"\n";
    return 0;
}

Here is an example of reading each character of standard input into a string.

#include <iostream>
#include <string>
using namespace std;
int main () {
  string docstr;
  while (!cin.eof()) { docstr.push_back(cin.get()); }
  docstr.pop_back(); // Ditch the last thing read, the End Of File FF.
  cout << docstr;
  cout << docstr.length() << endl;
  return 0;
}

iomanip - Manipulators

Instead of old C stdio.h printf formatting, C++ prefers you to use something called a "manipulator". The classic endl is such a thing. For more complicated manipulations, you’ll need to use <iomanip>.

Depending on how wild you get you may want to preserve stream formatting settings before mucking them up and then restoring them when you’re done. To save a copy of the current settings, use something like this.

// Include these...
#include <iostream>
#include <iomanip>
// Save existing settings.
ios:fmtflags preserved_flags= cout.flags();
int preserved_precision= cout.precision();
// Do some crazy stuff.

// Restore settings with this.
cout.flags(preserved_flags);
cout.precision(preserved_precision);

To pad with leading zeros (or any character) use something like this.

cout << setfill('0') << setw(10) << mynum << endl;

Here is a lesson about manipulators.

#include <iostream>
#include <iomanip>
int main () {
    std::cout<<std::setw(15)<<"Padded 15"
             <<std::setw(20)<<"Padded 20"<<std::endl;
    return 0; }

Besides the normal setw, there is also setfill, setprecision, and setbase. In Cpp11 there are some manipulators for money and time. (See here.)

See operator overloading below for examples, of how you can make your own objects do the right thing with cout.

stringstream

#include <iostream>
#include <string>
#include <sstream>

int main () {
    std::string stringifiednumber;
    float mynumber = 0;
    std::cout << "Enter number: ";
    std::getline (std::cin,stringifiednumber);
    std::stringstream(stringifiednumber) >> mynumber;
    std::cout<<"Plus one would be: "<<++mynumber<<"\n";
    return 0;
}

File Operations

#include <iostream>
#include <fstream>
#include <string>
using namespace std;

int main(){
    string line;
    // Create output stream for writing in append mode.
    ofstream f2write ("input.txt", ios::app);
    if (f2write.is_open()) {
        f2write << "\nThe End.\n";
        f2write.close();
    }
    else
        cout << "Unable to open file for writing";
    // Create input stream for reading.
    ifstream f2read ("input.txt");
    // The file is opened at ifstream creation.
    if (f2read.is_open()) {
        while ( getline (f2read,line) ){ cout << line << '\n'; }
        f2read.close();
    }
    else
        cout << "Unable to open file for reading";
    return 0;
}

I like to send output either to a file or if one is not specified, standard output. How can that be done? This is a setup that has worked for me.

void output_document(Obj &content,ostream &os) {
    os << content;                                 // Will be stdout or file.
}

if ((outfile[0] == '-') && (outfile[1] == '\0')) { // The standard output dash?
    output_document(TheContent,cout);              // Use cout as file stream.
} else {                                           // File name provided.
    ofstream f(outfile);                           // Create file stream f.
    if (f.is_open()) {                             // Open without problems?
        output_document(TheContent,f);             // Send f as the stream.
        f.close();                                 // Take proper care of f.
    } else                                         // Something went wrong.
        cout << "Error: Problem writing to:" << outfile << endl;
} // End real output file name provided.

Read Filenames Of A Directory

Note that while this does seem to work fine and it illustrates some interesting techniques, it takes 39x longer to run than simply doing ls /tmp. YMMV.

#include <iostream>
#include <string>
#include <vector>
#include <iterator>
#include <dirent.h>
using namespace std;

void read_directory(const string& name, vector<string>& v) {
    DIR* dirp = opendir(name.c_str());
    struct dirent * dp;
    while ((dp = readdir(dirp)) != NULL) {
        v.push_back(dp->d_name);
    }
    closedir(dirp);
}

int main() {
    vector<string> v; // Vector to contain strings for each file in dir.
    read_directory("/tmp", v);  // 1. string of dir 2. vector of strings of contents.
    copy(v.begin(), v.end(), ostream_iterator<string>(cout, "\n")); // Display them.
}

Note also that there is a std::filesystem::directory_iterator (ref) but that required turning on compiler options last I checked.

Memory

Some C++ specific keywords, new and delete, help with memory allocation and deallocation issues.

Functions

In C it is good practice to prototype functions (describe their input and output before using them).

Unlike C, in C++ functions can be overloaded. This means that their meaning can be redefined.

Also C++ can use functions inside of structures. This is not common but it hints at the more C++ way of organizing functionality, classes, discussed in the next section.

Unlike C, C++ allows the program to define default values for function arguments. This is valid.

int sum(int x, int y,int z=0,int w=0) { return x+y+z+w; }
sum(1,2); sum(1,2,3); sum (1,2,3,4);

If the number of arguments changing makes you apprehensive hold on to your hat because things get even more exciting with…

Variadic Arguments ...

Need a variable number of arguments? C++ can do that with variadic function parameters. To do this use ... (three periods) as the last parameter "name". Then in the function itself you can refer to some special variables related to the call. Then you can use va_list, va_start, va_arg, va_copy, va_end which are explained here.

There is some typical C++ syntax messiness with this feature. This sentence from the official reference helps one understand what they’re looking at when they come across multifarious syntax for variadic arguments in the wild.

This syntax for variadic arguments was introduced in 1983 C++ without the comma before the ellipsis. When C89 adopted function prototypes from C++, it replaced the syntax with one requiring the comma. For compatibility, C++98 accepts both C++-style f(int n…) and C-style f(int n, …).

Fortunately that’s all there is to know about ... syntax. Ha! Just kidding! Have a look over at template parameter pack syntax which also uses ...!

Deleted Functions

Sometimes you might see something like this.

class Something : public Something_base {
public:
   definitely_floats(float x) {return x*2;}
   definitely_floats(int x) = delete;
};

This is a C++11 style which is similar (but superior I’m told) to declaring a private function and then just neglecting to define it. This is to prevent it from being used. This way, by being explicit about it, you can get more sensible compiler errors.

Increment Operators

Prefix operators (e.g. ++var) increment the value and then return a reference.

Postfix operators (e.g. var++) create a copy of the variable, increment the value, then return the copied, unincremented value.

Also C++ has += and other such operators as found in Python.

Inline Functions

C++ discourages the use of preprocessor complexity. Instead, the idiomatic C++ way to do preprocessor functions is with the keyword inline.

Functor

I’m not sure if this is really a real thing or just a way to refer to a kind of usage but I’ll note it here in case it comes up. A functor essentially seems to be a class which includes a ‘type operator()(type arg){ def; }` overload function, i.e. overloading the parentheses that usually signal a function. This gives the class name the ability to look like a function and do this thing defined in the overload. The difference here between other function strategies is this functor can now carry around state in the class’ member variables.

Here’s a simple example of how this might look.

#include <iostream>
using namespace std;

template<typename T> int changeit(T process, float x) { return process(x); }

class Half   { public: float operator()(float x) { return x/2; } };
class Double { public: float operator()(float x) { return x*2; } };
class TimesLastResult { public: float last=1; float operator()(float x) { last*= x; return last; } };

int main() {
    Half decrease;
    Double increase;
    TimesLastResult warpspeed;
    cout << decrease(decrease(4.0)) << endl; // Returns 1 - Simply calling the functor.
    cout << changeit(decrease,2.0) << endl;  // Returns 1 - Passing desired functionality...
    cout << changeit(increase,0.5) << endl;  // Returns 1 - ...and necessary args.
    cout << warpspeed(2) << endl;          // 2
    cout << warpspeed(2) << endl;          // 4
    cout << warpspeed(2) << endl;          // 8  - This function is remembering its state.
    cout << changeit(warpspeed,2) << endl; // 16  - Can still be used modularly.
    return 0;
}

This example shows normal functors, how to use them in a modular interchangeable way and finally how the state features could be used. The TimesLastResult multiplies the supplied argument by whatever the last answer this function supplied was. That’s a strange kind of function, but possibly useful (the classic Fibonacci example might have been more "useful"). Normally a trick like this is just hidden in some big class but the point here is that it doesn’t have to be.

Lambda

Lambda expressions, also called "function literals", showed up in C++11. Lambda functions are anonymous functions in the same way that 2.5 in x=2.5 might be an anonymous float. Everything a lambda can do can be done other more verbose ways. For normal things that lambdas do, function pointers suffice just fine, however there are some added tricks to lambdas. The apparent similarity of lambdas to function pointers comes from the fact that a lambda creates a class which has a operator() so that it can look like a function and do the job of a function pointer. But this class can do some other things too like "capture" state, optionally by reference. The runtime object of this class is technically called a "closure" and holds the references or copies of the captured variables. The class is called a "closure class". If the capture is empty then the compiler may just create a function pointer. Note that proper function pointers will work anywhere while lambdas are scoped to where they are defined — a bad thing sometimes but usually probably a good thing.

In practice lambdas are mostly used to create little expressions for things like find_if, remove_if, count_if, sort, lower_bound, etc. They’re commonly used in thread programming and for special behavior with shared and unique pointers.

Lambdas can usually be spotted with a distinctive empty capture [].

[capture_clause](parameters)->return_type{statements;}
  • capture_clause - which outside variables are available to the lambda statements and whether to copy or reference them. See below.

  • parameters - even an anonymous function can have input. Even messy variadic input.

  • return_type - normally not explicitly specified and properly deduced for simple functions with less than 2 return statements. When the exit logic gets messy, this can be used.

  • statements - normal code with normal semi-colon terminations.

Nothing too complicated about that except for the capture clause. It is usually empty (capture nothing), but it can get absurdly complex. There are some quirky syntax tricks:

  • [&x] means x by reference.

  • [&x,y] means x by reference y by value.

  • [=] means capture all by value by copying. Probably unwise.

  • [=,&x] means copy all except x by value.

  • [&] means capture all by reference. Probably unwise.

C++14 has even more baroque "features" and syntax.

  • [x=x] make sure your external capture variables are copied to the closure’s variable.

  • [x=std::move(x)] on the other hand ensures a move.

Note that the scope on the left and right of the = here are different (left x is in the closure, right x is in the code defining the lambda). This is called "generalized lambda capture" and allows one to capture the result of an expression. Looks like a mess to avoid if possible.

auto mylambdafn= [](){ cout << "doing mylambdafn..." << endl; };
mylambdafn();

Control Flow

if-else
if (x>=y) {dothis();}
else if (x<y) {dothis();}
else {dothis();} // Optional.
case
int choice=1;
switch (choice) {
    case (0) : cout<<"no"<<endl;  break;
    case (1) : cout<<"yes"<<endl; break;
    default : cout<<"huh?"<<endl;
}
for
for (int i=0; i<10; i++) {
    std::cout<<i<<endl;
}
for with implicit type casting
#include <cstddef>
for (std::size_t i=0; i<10; i++) {

There is also a newish (C++11) range-based for more like Python or Bash.

for ( declaration : range ) statement;

The declaration is a named variable whose type is the type of the sequence’s elements. The range is some kind of container or array or sequence containing the type of the declaration variable. Something like this.

int a[] = {0, 1, 2, 3, 4, 5};           // A simple array.
for (int n : a) { action(n); }          // Do stuff with each n.
for (char c : "xed.ch") { action(c); }  // Iterate over each character.

This works for complex container objects too.

while
while (conditional) { do_stuff(); // Keep it up! }
do { do_stuff(); } while (conditional); // Make sure at least one happens.

Both break, to exit the loop immediately, and continue, to conclude the current loop body execution and go on to the next, are valid.

To get an infinite loop that needs a break to get out of (or not) here are options.

for (;;){... }
while(1){... }

Threads

There are three kinds of threads worth knowing about.

  • Hardware threads - Provided by the hardware to do computations on each core.

  • Software threads - Managed by the OS to keep the hardware threads loaded properly.

  • C++ threads - These objects from std::threads act as a handle to threads in the same way that programmed file handles act as handles to OS files.

You should consider using std:threads directly if you are trying to optimize a single program on a single platform. But for everyone else in the land of portable software that plays nicely with others, use the "task" oriented approach. Such an approach will look something like this.

auto fut= std::async(some_asynchronous_computation)

When used with the default launch policy, this spares you a lot of gruesome low level details and provides better return value (fut) and exception functionality. The default launch policy is to run the task asynchronously or defer it, whichever the compiler thinks best. This is equivalent to the previous async call.

auto fut= std::async(std::launch::async|std::launch::deferred,some_asynchronous_computation)

This should make it obvious how to constrain behavior to one or the other. Constraining to async seems to go with the spirit of it.

Pointers

int I=20, *pI;
pI= &I; // Pointer to I is the address location of I.
cout << *pI; // Dereference returning value pointed to by pI.

One thing to note about C++ is that using 0 and NULL used to be ok to refer to a null pointer. This is no longer polite. This can cause problems when overloaded functions can’t figure out if you mean an integer (as in 0) or a null pointer. For null pointers, the correct modern C++ way is to use nullptr.

Smart Pointers

A smart pointer was first part of C++98. In C++11, there are now three more types of smart pointers. These have pretty much all of the same functionality as normal pointers but with a lot of baggage to try to help keep things under control.

  • std::auto_ptr - Deprecated — only consider using for legacy requirements.

  • std::unique_ptr - Replaces auto_ptr but with correct copying. Actually, copying is not even a thing with this pointer but move is. If you could copy it, it wouldn’t be unique, would it? It is a move-only type. Converting to std::shared_ptr is ok. Destruction normally uses delete but can also use a custom destructor.

  • std::shared_ptr - Has reference counting for multiple ptrs with the same target. Double the size of raw pointers to store a pointer to a reference count (actually the "control block" where the reference count and other things are stored which makes it more than double). Must be atomic or bad things happen. Also creating multiple shared pointers for the same object is a bad idea; there will be multiple reference count accounting and the deletes will be more or less random. You can copy shared pointers for mostly the same intended (but correctly functioning) effect. Shared pointers have no normal array features, e.g. no operator[]; generally use std::array or std::vector instead.

  • std::weak_ptr - Like shared, but doesn’t increase reference count. Needs to check if object is still there. Usually created from std::shared_ptr. Valid when a something like a shared_ptr is needed but it may dangle. More can be found about when this might be applicable here.

auto mysharedptr= std::make_shared<MyType>(); // Ref count is 1.
std::weak_ptr<MyType> myweakptr(mysharedptr); // Ref count is 1.
mysharedptr= nullptr;                         // Ref count is 0. The MyType destroyed.
if (myweakptr.expired()) { // Do something... // Points to nothing so expired.

Note that the function is framed as expired() because testing for it being still valid is tenuous; this is because at any moment (e.g. between you checking and doing something about it) it could expire. You can get that behavior only by creating a std::shared_ptr from the weak one. That is an atomic check and grab which will be null if the std::weak_ptr has expired. Do that like this.

std::shared_ptr<MyType> ptrcheck= myweakptr.lock();

Smart Pointer Creation

To allocate smart pointers you could do something like this.

std::unique_ptr<MyClass> my_unique_ptr(new MyClass);

This makes you have to repeat the type and apparently has other problems. The modern recommended way is to do it like this with special functions designed for the purpose.

auto my_unique_ptr(std::make_unique<MyClass>());

Works with make_shared<Type>() too. (make_unique is C++14 and make_shared is C++11).

These functions work better almost always but may have problems if you need to have custom memory management, like your own operator new and operator delete. But that’s super exotic.

References

References are a feature specific to C++ not found in C. Although the subtleties get complex, the greatest utility of references is simply as a way to pass by reference to functions easier. You can still move things around by pointers if you want but references often allow function calls to be less complicated.

  • In Unix terms, I think of pointers as symlinks and references as hard links. The reference is the object accessed differently, not a pointer to an address that may not contain anything.

  • You can also think of a reference as a constant pointer.

  • Pointers are variables that contain memory addresses while references are additional definitions of compiler tracked objects. (The compiler thinks: "Ah, he’s calling x another thing, y, now too.") Of course the compiler can use the same machinery it uses for pointers for this but references can be implemented more efficiently. That’s up to the compiler.

  • References point to objects (whose address a reference shares), while pointers can point to other pointers, ad infinitum.

  • References can not point to other references. (You are forbidden from specifying any such thing, however, if a compiler causes this to happen, say by some weird template instantiation or auto usage or messy typedef, the two references "collapse" using a baroque heuristic.)

  • References can (should) not normally be NULL.

  • References can not iterate using pointer arithmetic.

  • Pointers need to be dereferenced with *, or -> for class members, while references can be dereferenced with . like the referent ("automatic indirection").

Simple Demonstration Of References
#include <iostream>
using namespace std;

// Function with reference parameters.
void one2theother(int &from, int &to) { from--; to++; }
// Function with reference parameters returning a reference.
int &add2together(int &a, int &b) {
    int s; int &r2s=s; r2s= a+b; return r2s; }

int main () {
    int var= 10; int var2= 99;
    int &ref2var= var;
    cout << var << endl      // 10
       << ref2var << endl;   // 10
    ref2var++;
    cout << var << endl      // 11
       << ref2var << endl;   // 11
    var++;
    cout << var << endl      // 12
       << ref2var << endl;   // 12
    one2theother(var,var2);  // Function using references.
    cout << var << endl      // 11
       << ref2var << endl    // 11
       << var2 << endl;      // 100
    cout << add2together(var,var2) << endl; // 111
    return 0;
}

Here is a lot of expertise on the topic for those who really need it. And once you think you know how great references are, you can start to doubt yourself by wondering if passing a reference to a single char is actually made less efficient than simply passing the value directly — here are some people who have pondered this quandary. Non-theoretical practical answer: doesn’t matter.

Rvalue References

Newish C++ is littered with double ampersands as in this parameter definition: MyClass&& x. What the heck is that all about? These are "rvalue references". They are also sometimes called "forwarding references".

An rvalue (see values below) reference is mostly used to bind to temporary objects in order to make them more efficient. They also are useful in "move semantics" and "perfect forwarding" which is about juggling items in memory in a sensible way. They can only bind to objects for which moving in plausible.

This apparently is very useful in template code. In template argument deduction there is a concept called "universal references" which is subtly different but uses the same double ampersand. There something like MyClass&& x could refer to a reference or the real object. These arcane subtleties are discussed here. One general rule is that if there will be magical type deductions as with auto or templates, then the && syntax is a universal reference and not necessarily constrained to an rvalue reference. An important implication is that if you use this kind of trick it’s best not to make the universal reference an argument of overloaded functions. This will tend to try to fit the universal reference before fitting what you really wanted it to fit. Ah, automagical — not always so auto or magic.

If you want to make sure these automagical helper monkeys stay in their cages, you can use the explicit keyword which will prevent implicit conversions and copy initializations. Another way to get universal references to behave "explicitly" in your overloaded functions is to use what’s called "tag dispatch" this is where you add bogus arguments so that the function signature is certain to be the correct match.

Values

In C++, especially the modern species, you see the term "lvalue" and "rvalue" pop up a lot. For some reason it is taken for granted that programmers will instinctively know the etymology of these words. I used to think it was "left value" and "right value" as in which side of the equals sign something like x=3; was on. Wikipedia hints, misleadingly I suspect, that lvalue might have something to do with "location".

lvalue properties
  • Traditionally on the left side of an assignment expression.

  • Its address can (usually) be taken.

  • Designates a function or object (usually).

rvalue properties
  • Traditionally on the right side of an assignment expression.

  • Its address can (usually) not be taken.

  • A temporary object or some other kind of value not associated with an object.

This lvalue and rvalue stuff is bad enough to have to think about but modern C++ spirals out of control with three more types.

There are now the following value types.

  • rvalue - Fun fact: rvalue references returned from functions are themselves rvalues.

  • lvalue - A "parameter" is always an lvalue. void f(MyClass&& x); the parameter x is still an lvalue even if its type says otherwise.

  • glvalue - Generalized lvalue, a subspecies of lvalue.

  • xvalue - Expiring value referring to an object whose resources can be moved because it is nearing its destruction. Perhaps as function return values which are exotic reference things which necessarily will be gone after the return. Something like that.

  • prvalue - Pure rvalue. Like an xvalue but for simple rvalue non-reference things (themselves).

The horrendous gory details can be explored here.

Move and Forward

The functions (function templates to be exact) std::move and std::forward are interesting in that they do not move or forward (respectively) anything. They are compile time mechanisms for elaborate casting which I feel is the most important thing to understand about them — they do nothing at runtime. It seems that move should have been named something like rvalue_cast. Since rvalue objects are the kind that can be properly moved, the std::move function does provide a running start to that actual functionality.

So what do they do? The std::move casts an argument to an rvalue. The std::forward does the exact same thing but only in limited cases.

If you’re fighting with these mechanics, also keep in mind std::remove_reference which strips the l- or r-valueness.

Move requests on const objects are silently transformed to copy operations (losing any efficiency you may have envisioned).

The std::forward function (template) is mostly used in a function template taking a universal reference parameter that will be forwarded to another function. Since arguments are lvalues, if you have an argument that needs to stay an rvalue and get passed on as such, that’s what std::forward is good (known) for. The condition it checks for is if the argument it is looking at is an rvalue. If not, then it just passes it on without any exotic casts. In theory the std::move function could always be replaced by the more comprehensive std::forward. But subtle differences in "clarity", I suppose, have produced both.

Classes

C++ features organization by classes.

Special member functions are the ones that C++ can create implicitly.

Table 1. Special Member Functions

default constructor

X()

destructor

~X() // C++11 forces noexcept

copy assignment

void operator=(X &src)

copy constructor

X(X &src)

move constructor

X(X&& src) // new in C++11

move assignment

X& operator=(X&& src) // new in C++11

In C++11 there is a way to actively produce these special member functions which, under some circumstances (not ever used, etc), don’t get auto-generated. This uses the keyword default.

X(const X&) = default; // Normal copy ctor is fine, make one for X.
X& operator=(const X&) = default; // Normal copy assignment ctor is ok too.
X(X&&) = default; // Normal moving.
X& operator=(X&&) = default; // Normal moving assignment.

This might just be easier to comprehend as a reminder that these things can (and now will) autogenerate.

Example of Using Classes
// cxe- Wed May 12 12:22:10 PDT 2004
// This is a test of using inheritance to create a containable class (or array
// in this example) of heterogenous objects. The goal will be to store 2
// classes in the same array in such a way that they are usable.

#include <string>
#include <iostream>
using namespace std;

class Number {  // This is the base class.
   public:
      Number() {}
      virtual void show() { cout << "No base class data!" << endl; }
   private:
}; // end class Number

class Roman: public Number {
   public:
      Roman operator=(string p) { pretium= p; return *this; }
      void show() { cout << "Roman:" << pretium << endl; }
   private:
      string pretium;
}; // end class Roman

class Arabic: public Number {
   public:
      Arabic operator=(int v) { value= v; return *this; }
      void show() { cout << "Arabic:" << value << endl; }
   private:
      int value;
}; // end class Arabic

int main() {
   Number z; //can't do anything with z
   Arabic a; a= 19;
   Roman  r; r= "XIX";
   cout << "Objects as themselves, no container ----------" << endl;
   z.show(); a.show(); r.show();

   Number n[3]; // Array of base class objects
   n[0]= z; n[1]= a; n[2]= r;
   cout << "Objects in container of baseclass ----------" << endl;
   n[0].show(); n[1].show(); n[2].show();

   Number *p_n[3]; // Array of pointers to Numbers
   p_n[0]= &z; p_n[1]= &a; p_n[2]= &r;
   cout << "Objects in container of baseclass pointers ----------" << endl;
   p_n[0]->show(); p_n[1]->show(); p_n[2]->show();

   return 0;
} // end main

This outputs the following.

Objects as themselves, no container ----------
No base class data!
Arabic:19
Roman:XIX
Objects in container of baseclass ----------
No base class data!
No base class data!
No base class data!
Objects in container of baseclass pointers ----------
No base class data!
Arabic:19
Roman:XIX

Note that the default access is private so by listing them before public, you can save that keyword. I think it’s better to just be explicit though.

Declarations will often need the class namespace. This looks like this.

retVar ClassName::somefunction(int x,int y);

The protected access control specifier means that the item specified is treated like public by derived classes and private from unrelated ones.

Slicing Problems

C++ has a troublesome topic of discussion called the "slicing problem". This has nothing to do with Python slicing. It looks a bit like this.

class A {int alpha;};
class B:public A {int beta;};
B b; A a= b;

In this code, b has an alpha and a beta, but a does not have a beta even though it was assigned from an object with one. That beta is considered to have been "sliced" out of the object.

const Member Functions

If you have a situation like this

const Mything the_unchanging_thing= Mything("Always this.");
the_unchanging_thing.dump();

The dump member function probably won’t compile because the compiler can’t be sure that the dump() function won’t mess with the calling object. And since this particular calling object, the_unchanging_thing, is constant, that would be wrong.

The way to handle this is to define the dump() function as a "const Member Function" (that’s the official way to refer to it). Add the const keyword to the end of the declaration and definition.

void dump() const;

friend

Sometimes you want to give access to other functions that are actually not part of your class. This is what friend functions can do. Use friend keyword in the declaration, not the definition.

Confusingly, you must put the friend function declaration in the class it doesn’t belong to prefixed with the friend keyword.

friend MyClass operator+(double x, const MyClass &mc);

This now can go in the MyClass declaration even though it’s not part of MyClass. It’s just a helpful random function that can now access MyClass as if it were a part of it. Note that this example helps for this order of arguments. If the order is reversed, the MyClass operator+ can just be overloaded the normal way. It seems common to use friend functions when overloading operator<<().

Classes can be friends too. By doing something like this.

class Body {
  public:
    friend class Clothes;
  ...

This type of arrangement will allow Clothes to access Body’s private parts.

virtual

The virtual keyword is confusingly used for different purposes depending on context. Here are two of the uses. There may be more.

  1. A function declared virtual means that an existing overriding function in a derived class is invoked.

  2. An inheritance relationship declared using keyword virtual between classes Derived1 and Derived2 that inherits from class Base means that another class Derived3 that inherits from Derived1 and Derived2 still results in the creation of only one instance of Base during instantiation of type Derived3.

See Abstract Base Classes for an explanation of "pure virtual functions".

One slightly tricky thing that can plague setups that want to leverage virtual functions is something like the following example where I want to have different backend output systems for some internal data. Simplified for illustrative purposes, here’s a plausible way to set something like this up.

#include <iostream>
using namespace std;
class Backend {             public: virtual string make_bold(const string &l) { return "*"+l+"*"; } };
class Backend_HTML:public Backend { public: string make_bold(const string &l) { return "<b>"+l+"</b>"; } };
class Backend_TeX: public Backend { public: string make_bold(const string &l) { return "{/bf "+l+"}"; } };
string do_someformatting(Backend outputEngine){return outputEngine.make_bold("The text.");}
int main() {
    Backend_HTML outputEngine; // The goal is to control output style simply by how this is typed.
    cout << do_someformatting(outputEngine) << endl;
    return 0;
}

Because I declared the outputEngine variable to be a Backend_HTML, you might expect the do_someformatting() function to produce the HTML version. But it does not. It produces the virtual function’s *The text.*. What is going on? It’s subtle but you must change the function declaration of the function that works with these overridden objects so that they show up as references. Note the &.

string do_someformatting(Backend &outputEngine);

Without this, the function insists that the HTML outputEngine object supplied be hammered into the generic base class. By using a reference to the &outputEngine the result is <b>The text.</b>.

Virtual Data Member Attributes

Nope. Don’t think it can be done. Use a Rube-Goldberg getter function to supply your derived classes refined values. Or use Python.

Operator Overloading

One of the many idiosyncratic things about C++ is that it is one of the few languages that allow you to muck about with redefining much of the core syntax. Don’t like how + adds numbers? Well, you can change it. Obviously this can produce horrendous obfuscation, but generally it’s quite handy.

One of the most common uses for operator overloading is to make a function that can allow your custom classes to be included in normal stream operations. In the following example, I have a Block class that I’d like to be able to "print out" using cout.

ostream &operator <<(ostream &s, Block b){
    s << "Block (" << b.queryBlockType() << "):";
    return s;
}

Note that this is not a member function. This is just a global function. That said, you need to give this global function access to the data it will likely be using from the custom class. That is done with a friend function (see also that section). That looks like this.

friend ostream &operator <<(ostream &,const Block &);

I’m not sure that’s technically a proper declaration; it’s more like a decoration referencing a function template that must be spelled out like a declaration. Whatever it is, it does go in the class definition.

Need to worry about postfix vs. prefix? Lucky you! This example is probably wrong, but it’s in the right direction.

X &operator ++ (int) {X t; t.v= v++; return t;}
X &operator ++ () {X t; t.v= ++v; return t;}

The & is optional but almost always present to lighten up the call by making the default argument a reference. Note that there are some things you probably should not think about overloading.

Override (The Keyword)

When a base class function is declared virtual its corresponding derived class functions should override it. It turns out that sometimes subtle errors can happen if the derived class has some defect in its correspondence to the base class. To make the errors less subtle and more obvious to the compiler such that sensible errors will be produced, C++11 offers the override declaration. Basic usage looks like this.

class Universal {
public:
    virtual void myfn();
};
class Specific: public Universal {
    void myfn() override; // Optional to begin with "virtual" here too.
};

One bizarre caveat on the override specifier is that it only is a keyword if it is in a proper place at the end of a member function declaration. This means that if you want a function called override() or a variable or whatever, you can do that. Obviously that’s going to be misleading these days to those in the know — but not to those really in the know. Obfuscated C++ writes itself! Gah!

A similar specifier is final which indicates that the function or class should not be overridden. It is in its final form. Or something like that — smells like Java.

Reference Qualifiers

Getting into crazy weird stuff is easy with C++ and my favorite example of "ok, you’ve gone too far" is reference qualifiers. I’m not going to pretend to understand the gory details but essentially you can specify if derived classes can override (not overload) base class functions depending on whether or not the member function is an lvalue or an rvalue.

Clearly that is ridiculous and the whole language should be scrapped if we need to regularly deal with ridiculous error bait like that. But I’m including it for completeness so that I can hopefully recognize this for what it is if I ever stumble across it in the wild. Here’s the syntax that should tip you off to this "feature".

Class Myclass {
public:
    void weirdfunction() &;  // Only when *this is an lvalue.
    void weirdfunction() &&; // Only when *this is an rvalue.
};
Myclass x;                   // Ordinary instantiation which is lvalue.

Note that if you ever use reference qualifiers you need to make sure all overloads use them otherwise the ambiguous ones may take precedence and screw things up.

I don’t even know when the function’s context would ever be rvalue (factory functions?) but that should be enough of a syntax hint to send you off in the right direction for proper research into the topic.

Abstract Base Classes

Taking some kind of obnoxious programming test? I had never heard of this and I suspect it has something to do with Java where abstract is a keyword; it is not in Cpp! But there are abstract base classes, sometimes referred to as ABC, in Cpp. An abstract base class is really just a class that contains one or more pure virtual functions. Class declarations containing at least one pure virtual function will not allow objects to be instantiated from that class.

A "pure virtual function" is one that ends with =0 like this.

void Move(int dx,dy) = 0;

That’s it. The =0 in the prototype means that the ABC doesn’t need to define the function. Also note the const member function version.

void Show(int dx,dy) const = 0; // But don't modify the calling object.

Member Initialization Lists

In class definitions the constructor can have a list of members with their correct initial values defined. These are placed after the constructor name and parameters, followed by a : and before the body of the constructor. The following are very similar. The first is preferred since it avoids unnecessary copies.

MyClass(int some_init_args):member1(5){}
MyClass(int some_init_args){member1=5;}
Example of Member Initialization Lists
#include <iostream>
class Parent {
    public:
    Parent( int x ) {
        std::cout << "Parent's constructor"
        << " called with " << x << std::endl;
        }
    };

class Derived: public Parent {
    public:
    Derived() : Parent( 10 ) { // With "Member Initialization List".
        std::cout << "Derived's constructor" << std::endl;
        }
    };

class Strclass {
    public:
    Strclass() : thestr("This is the init string.") {
        std::cout << thestr << std::endl;
        }
    private:
    std::string thestr;
    };

int main() {
    Derived a_derived_instance;
    Strclass somesc;
    }

Exceptions

Recovering from errors in C is done by explicitly planning for every specific erroneous condition. In C++ there is a system of "exceptions" where (specifically) unanticipated errors can be treated reasonably.

While it is critical to understand exceptions I personally have some misgivings about them which are well documented in my Python notes. Without going into details here, I’ll sum up my personal opinion about C++ exceptions by quoting the Google C++ Style Guide which simply says, "We do not use C++ exceptions."

Here is a rough idea of how C++ exceptions work.

Example Of Exception Use
#include <iostream>
using namespace std;

void thefunction() { throw 99; }

int main (int argc, char *argv[]) {
    try {
        if (argc > 1){ thefunction();}
        else { throw '?';}   }
    catch(int e) {  // The catch is chosen based on its type.
        cout << "Exception number " << e << " has occurred." << endl;
    }
    catch (...) {  // If the type sent by throw is not defined, go here.
        cout << "Unknown exception has occurred." << endl;
    }
    return 0;
}

When this code is run with arguments it returns:

Exception number 99 has occurred.

When this code is run without arguments it returns:

Unknown exception has occurred.

Note that the catch statement is chosen based on the type specified by the throw command. In this simple example, this is not remarkable, but when defining your own types with classes, this mechanism can be very useful in organizing code to react to errors arising from different causes.

There are much fancier ways to use exceptions. You can define your own by inheriting standard exceptions. You can also catch and handle standard exceptions your own way. They can be nested such that the inner exception passes the information through to the outer ones.

Trying to document all weird syntax one might encounter, note that there exists a C++11 declaration specifier, i.e. a keyword, called noexcept. This is used to declare functions that are guaranteed not to ever emit exceptions. The point of this is that when the compiler must worry about exceptions, performance can be hit. This feature can allow the compiler to do the best thing. The syntax looks like this.

ReturnType myfunction(parameters) noexcept; // Most optimizable.
ReturnType myfunction2(parameters) throw(); // C&#43;&#43;98 style.
ReturnType myfunction3(parameters);         // Exceptions ahoy!

That throw() syntax is valid but not exactly the same as the noexcept syntax. Gah! Best to just leave the whole topic alone unless you step in a pile of it in someone else’s code, or it otherwise causes trouble.

Templates

Functions
template <typename T>
T functionName (T  parameter1,T  parameter2,...) { /* Function template. */ }

template <typename T1, typename T2>
T2 functionName (T1  parameter1,T2  parameter2,...) { /* Multiple types. */ }
Classes
template <class T>
class Number
{ private: T value; };

IntArray::IntArray(){ /* Normal constructor. */ }

template<class Type>
Array<Type>::Array(){ /* With template. */ }

Debugging

Since C++ is famous for having millions of lines of error output it’s good to intercept this where possible. The static_assert command will print a message if a condition is met at compile time.

For example, this checks to see if negative integers round down when divided.

static_assert(-3/2==-1)
static_assert(-3/2==-1, "Negative division rounds towards positive.")

The normal assert is for ensuring things are in order for run time and works the same way.

Standard Template Library

The near universal detest for STL in game development makes each studio’s code a silo of private libraries, which is unfortunate.

You don’t use STL where you need max performance, but performance isn’t the top priority for most code, even in games.

I don’t like STL much and rarely use it, but I do really like standards. The library situation with C++ is really a shame.

#ID_AA_Carmack (2014-04-05)
— John Carmack

Both C and C++ are very spartan languages and in order to do anything useful in either you pretty much need to write some tools to manage simple flexible data structures. This has been thought out in C++ with the Standard Template Library or STL.

Note that in modern times the STL is actually a subset of the C++ standard library that was inspired by an ancient template library that got integrated. Another way to say "STL" is roughly something like "containers/iterators of the standard library".

STL mostly provides templates that allow programs to easily create simple but powerful data structures for all kinds of pragmatic uses. This is the kind of stuff that higher level languages like Javascript and Python take for granted.

Containers
Container Adaptors
  • priority_queue

  • queue

  • stack

iterators

Iterators are pretty important in normal C++ and are pretty much how you rummage through STL containers of data. And lots of other things. You can have an iterator type that looks like this.

typedef std::vector<int>::iterator MyIterType;

One interesting thing that seems bonkers to me is that you can have, and should prefer, constant iterators. It seems to me that if an iterator’s whole point is going from one thing to another, that’s fundamentally not very constant. Here’s an example.

typedef std::vector<int>::const_iterator MyConstIterType;

My limited understanding (here’s more) is that the const_iterator type points to different stuff, it’s just that the stuff is immutable. Still look out for it and, in theory, if you can use it, the const gods will smile upon you.

Vector

A vector container is essentially a dynamic array. It has most of the advantageous properties of regular C arrays, mostly contiguous memory that can be accessed with predictable strides. Unlike regular C arrays, a vector can be dynamically resized as needs grow. This implies that vectors hog more memory than you may actually need them to, just in case you eventually want to use more than you thought you would. This also implies that once you use more than even this amount of memory, that an abrupt allocation of yet more memory may perhaps be needed along with a physical reshuffling of the contents; I don’t know if this can inject weird choppy performance issues, but it’s something to think about. The strategies used by vector to allocate additional memory are implementation dependent but seem to try to keep log(size) performance (adding twice as much as you had before upon running out).

The following sample program shows the basic STL container usage with a "vector" template.

#include <iostream>
#include <vector>              // <---- Don't forget!
using namespace std;
int main() {
    vector<int> V1; // Define a vector of integers.
    V1.push_back(9); V1.push_back(6); V1.push_back(3); // Load vector.
    for (int i= 0; i<V1.size(); i++) { cout << V1[i] << endl; } // Display values.
    vector<int>::size_type v_st= V1.max_size(); // Note namespace to use size_type.
    cout << "Max number of elements in a Vector<int>: " << v_st << endl;
}

Methods for vector include:

  • empty - Tests if container is doing any containing.

  • push_back - In software engineering English "append". Relatively quick. Cpp11 emplace_back follows the plan of emplace.

  • pop_back - Remove item from end. Relatively quick.

  • insert - Arbitrary insertion. Maybe slow unless near the end and reallocation can be minimized. There is also Cpp11 emplace which allows construction and insertion.

  • emplace - Insertion functions take objects to be inserted but emplacement functions take constructor arguments for objects to be inserted. This can matter, for example, when dealing with string literal constructor arguments vs. actual std::string objects. Note also things like myvector.emplace(myvector.begin(),"new winner"); which can be used where you might expect an "emplace_front".

  • erase - Arbitrary removal (not just clearing, item size() is decreased). Also maybe slow unless near the end. I’m not sure if memory is reallocated down ever with this method, but it could be.

  • size - How many elements defined and present.

  • capacity - How many elements have been automagically provisioned for before the next reallocation would be required.

  • resize - Tries to set the number of items to that specified. If there were more items, they get harshly jettisoned.

  • reserve - Like a faux gearshift lever for an automatic transmission, you can ask to manually meddle in the automatic memory allocation. Or how about Cpp11’s shrink_to_fit which may do what’s on the tin (including remapping the whole thing) or, interestingly, it may do nothing.

Deque

The double-ended queue is similar to a vector in that elements can be accessed with random access indexing. The major difference is that items can be inserted at the beginning of the array while vectors allow only the end to expand. As a consequence of this feature another difference is that the deque is not guaranteed to live in contiguous memory. This means that offset pointers can’t be used, as with vectors, to access other items; if you try it will produce random nonsense behavior. The deque uses complicated chunks of memory that it grows as needed where needed. By splitting the container internals, better edits may be possible from the middle of the object and excellent edits are expected at either end. This kind of structure might be ideal for a FIFO queue.

Methods for deque include:

  • push_back, push_front - Add an item to the end or beginning.

  • emplace_back, emplace_front - Compose and add item to end or beginning.

  • pop_back, pop_front - Remove an item from the end or beginning.

  • insert - Add item to arbitrary location.

  • emplace - Compose and add item to arbitrary location.

  • erase - Remove item from arbitrary location.

  • clear - Remove all items from container.

  • swap - Exchange contents of two deque objects.

  • size - Returns number of items.

  • empty - Check if container is containing.

  • resize - Set the container to a limited specified number of items, losing any surplus.

  • shrink_to_fit - Asks the container to try and refactor to minimize memory usage so that it is just sufficient to contain the current items. Note that this is mostly a courtesy and not guaranteed to do anything.

List

An STL list is a doubly-linked list. It’s quick to insert one or many anywhere, but slow to find particular items deep in the chain. This means that inserting can be slow if you need to find the insertion point first. However it also implies that editing the ends of the chain is going to be quick.

Don’t forget to #include <list>.

Methods for list include:

  • size - How many elements (not storage/bytes). max_size for architectural top end.

  • assign - Fill in a particular value for the whole list or just a range, three6s.assign(3,6). Can be used to do a deep copy with something like mytargetlist.assign(mysrclist.begin(),mysrclist.end()); Playing with the iterators there seems to be the way to get slice functionality.

  • insert - Add existing element. emplace to construct and add (all emplace functions are Cpp11). Inserts before current item. This can also put multiple elements into a list; the args are iterator position of target, iterator position start of source (item included in operation), and iterator position of end (item not included).

  • push_front,push_back - Replace push with emplace to construct and insert.

  • pop_front,pop_back - This returns nothing, so it’s really a "drop" in how I’d think of these things.

  • back - like end but not an iterator to one past the end, and simply returns a reference to the last item.

  • begin,end - returns an iterator to first, and just past last. If you’re at end, you’ve already done all of them.

  • advance - Moves the iterator the number of int provided. E.g. auto myliststart=mylist.begin();std::advance(myliststart,3)

  • erase, clear - Removes an element or range. Or remove all content. Use empty to check if empty.

  • remove and remove_if - Removes elements that match specific values or other conditions.

  • unique - Remove duplicates.

  • reverse - Change the order of elements.

  • sort - Unadorned, uses <. Can use custom comparison function. Note the difference between this template method and the generic STL sort which requires a random access container. Stick with the built in list sort method for lists.

  • merge - Combine ordered lists into another ordered list.

  • splice - Move elements between lists.

Here is an example of using a linked list. One helpful feature is that you can insert into the beginning of the list without actually remapping everything else. This is a rough implementation of the Unix tac command which reverses lines of input. The reversing is done simply by inserting each line read into the list of lines instead of appending each.

#include <iostream>
#include <fstream>
#include <list>
using namespace std;

void readit(istream& ins,list<string>& lines){
    string line;
    while (getline(ins,line)){lines.push_front(line);}
}

int main(int argc,char** argv){
    list<string> lines;
    if (argc>1){ // A file name argument should be present.
        ifstream ifile(argv[1]);
        if (ifile.is_open()) { // Double check that it opened ok.
            readit(ifile,lines);
            ifile.close();
        }
        else // Can't open the file for some reason.
            cout<<"Error: Unable to open file for reading!!"<<endl;
    } else { // No arguments? Use standard input then.
        readit(cin,lines);
    }
    for (list<string>::iterator i=lines.begin();i!=lines.end();i++)
        cout<<*i<<endl;
    return 0;
}

Note also this program roughly shows how to handle reading standard input or a file specified. Also note that the reverse method could have been used, perhaps with slightly more clarity of purpose.

Another quirk of lists is that because it’s more of a linked chain — importantly, of arbitrarily sized items — it’s kind of weak on other simple features like spitting out what position a program is currently iterating over. Since it just moves around from node to node on the linked graph, it actually doesn’t really know much about the big picture. This means that some obvious strategies may not work as in this example where I want to know if the iterator, i is on the 2nd item.

if (i - myvector.begin()) == 1) {...      // Totally fine and quick, for random access iterators only!
if (i - mylist.begin()) == 1) {...        // This will not compile!
if (distance(mylist.begin(),i) == 1) {... // This will be slow, but will work.
i2= mylist.begin(); i2++; if (i == i2) {... // Not sure if this is a reasonable approach.

Other Lists

I have notes about a singly-linked slist but this appears to be nonstandard. And it looks like Cpp11 has forward_list for that purpose.

Reserved Keywords

asm, auto, bool, break, case, catch, char, class, const, const_cast,
const_iterators, continue, default, delete, do, double, dynamic_cast,
else, enum, explicit, export, extern, false, float, for, friend, goto,
if, inline, int, long, mutable, namespace, new, operator, private,
protected, public, register, reinterpret_cast, return, short, signed,
sizeof, static, static_cast, struct, switch, template, this, throw,
true, try, typedef, typeid, typename, union, unsigned, using, virtual,
void, volatile, wchar_t, while

Option Parsing

My C notes have a reasonable example of option parsing using getopt_long(). It’s a perfectly good way to do option parsing and works fine in C++. It uses old C style strings — it does not know about booleans, and is not consistent with normal C++ style. I wrote a more idiomatic version that despite being three times larger is arguably easier to use.

The main weirdness to get over is that what I’d really like is a function called optval() that returns the option’s value no matter what type it may be. However, you can not overload functions on just return type alone. So the work around is to pass in a variable of the correct type. This first of all assures you (and the compiler) know and have a good handle on what exactly that type is, and second allows you to just pass the variable you want to set as a reference and it will get set. The value is also returned if that’s helpful. If you don’t have a specific bool or whatever that you want set, you can pass in nonce member variables that exist just to be passed for this purpose. This is shown in the main function of the example.

#include <getopt.h>
#include <iostream>
#include <string>
#include <cstring>
#include <vector>
using namespace std;

class Config {                                                                 // == Defining ==
    public:
        Config(const int argc,char **argv); // Note default ctor works too; it does not parse.
        void parseopts(const int &argc,char **argv); // This function actually does the parsing.
        string optval(char c,string &val);  // Use a short opt letter to set and return its string.
        int optval(char c,int &val);        // Use a short opt letter to set and return its int.
        bool optval(char c,bool &val);      // Use a short opt letter to set and return its bool.
        vector<string> arglist(); // Args not related to options (e.g. often filenames to process).
        int i= 0; string s= string(); bool b= false; // Generic types. Use with optval() if no ref handy.
        string help();                      // Where the help text is generated.
    private: // Put all command line controlled settings with their defaults here.
        bool verbose= false;
        int debug= 0;
        string outfile= "-";
        vector<string> filelist; // This created from the non-option argument list.
}; // End class: Config
string Config::help() {                                                        // == Describing ==
    string h=  "usefulprogram - Chris X Edwards - 2021\n";
    h+= "-h,--help              This message.\n";
    h+= "-v,--verbose           Verbose messages.\n";
    h+= "-d[L],--debug[=L] Set  debug level, 1 when active and unspecified.\n";
    h+= "-o,--output <file>     Output file, default is standard output.\n";
    return h;
} // End function: Config::help()
Config::Config(const int argc,char **argv) { // Special constructor.
    parseopts(argc,argv); // Sensibly parses the options if given the argc and argv.
} // End Config::parseopts()
void Config::parseopts(const int &argc,char **argv) {                          // == Processing ==
    while (true) {
        static struct option long_options[] = {
            {"help",    no_argument,       NULL, 'h'}, // Bools work well in C++.
            {"verbose", no_argument,       NULL, 'v'}, // Verbose output.
            {"debug",   optional_argument, NULL, 'd'}, // With -d3 or --debug=3 specify level. Or -d to activate at defatult.
            {"out",     required_argument, NULL, 'o'}, // Output file. - is stdout which is default.
            {0,         0,                 0,      0}  // Signal end of options with a set of zeros.
        }; // End opt struct data.
        int o= getopt_long(argc, argv, "hvqd::b:eo:f:S:", long_options, NULL); // Returns option index.
        if (o == -1) break; // Signals end of options.
        switch (o) {
            case 'h': cout << help(); exit(EXIT_SUCCESS);
            case 'v': verbose= true; break;
            case 'd': if (optarg){ debug= atoi(optarg); } else { debug=1; } break; // Arg optional! E.g. `-d3 --debug=3`
            case 'o': outfile= optarg; break;
            default: cout << "Unknown option:" << o << endl; return;
        } // End switch construct.
    } // End while loop.
    while (optind < argc) { // Load any remaining command line arguments (not options).
        string s= string(); // Create a new empty C++ string.
        for (int i=0;i<=strlen(argv[optind]);i++) s.push_back(argv[optind][i]); // Construct string.
        filelist.push_back(s); // Add string to vector of arguments.
        optind++;
    } // End while still arguments.
    return;
} // End function: Config::parseopts()
bool Config::optval(char c,bool &val) {                                        // == Accessing ==
    switch (c) {
      case 'v': val= verbose; break;                                           // Can't override just on returns.
      default: cout << "Bad flag." << endl; // Bad.                            // So a correct type is passed in.
    }; // End switch.
    return val;
} // End function: Config::optval() for string
string Config::optval(char c,string &val) {
    switch (c) {
      case 'o': val= outfile; break;
      default: cout << "Bad string option." << endl; // Bad.
    }; // End switch.
    return val;
} // End function: Config::optval() for string
int Config::optval(char c,int &val) {
    switch (c) {
      case 'd': val= debug; break;
      default: cout << "Bad numeric option." << endl; // Bad.
    }; // End switch.
    return val;
} // End function: Config::optval() for int
vector<string> Config::arglist() {
    vector<string> v; for (string s:filelist) v.push_back(s);
    return v;
} // End function: Config::arglist()

int main (const int argc, char **argv) {                                       // == Using ==
    Config C= Config(argc,argv);
    cout << "Verbose is:"     << C.optval('v',C.b) << endl; // A bool.
    cout << "Debug level is:" << C.optval('d',C.i) << endl; // An int.
    cout << "Output file is:" << C.optval('o',C.s) << endl; // A newfangled  C++ string.
    for (string s:C.arglist()) cout << s << endl;
} // End main.

cmath

Fancier math. Trig, logs, exp, sqrt, ceil, floor, abs. And wacky stuff like isnan.

#include <cmath>
M_PI // Is pi.
std::pow(base,exponent) // Exponents.
NAN // Is constant.

Set

A set is a container whose elements are always ordered (not sorted) and unique. Sets can be handy when trying to count unique items, even mildly complex ones as shown here with pair containers.

#include <iostream>
#include <utility>
#include <set>
using namespace std;
int main(void) {
    set<pair<int,int>> s;
    pair<int,int> p; // Not strictly necessary here.
    cout << s.size() << endl;    // Outputs: 0
    p.first= 0; p.second= 0; s.insert(p); // 1
    p.first= 1; p.second= 2; s.insert(p); // 2
    p.first= 3; p.second= 4; s.insert(p); // 3
    // Showing different way to compose set.
    s.insert(make_pair(5,6));             // 4
    s.insert(make_pair(1,2));    // Redundant, ignore.
    s.insert(make_pair(3,4));    // Redundant, ignore.
    cout << s.size() << endl;    // Outputs: 4
    return 0;
}
  • clear - Remove all elements from object.

  • insert - Put an item into the container. There is no sense of front or back since the item itself defines its place in the structure.

  • emplace - Composes and inserts an item. Also note emplace_hint which is similar but also takes a likely neighbor (one higher) and if that neighborhood is actually correct, the insert can be a lot quicker.

  • erase - Removes an item. This can be specified with the position index or by value which, in a set are pretty much the same thing.

Unordered Set

An unordered_set does not maintain an order. These can be quicker than regular sets. This is a C++11 thing.

Multiset

Allows duplicates.

  • find - Allows you to find the one or many items that match what you’re looking for.

Unordered Multiset

If you don’t want a strict ordering and you want duplicates to be valid, the unordered_multiset is a Cpp11 thing. For simplicity, imagine a Python dict where the keys are combined with an invisible nonce and there are no values; something like that.

Pair And Tuple

The pair container — which came first — is a specific case of a std::tuple with two elements. Or thought of another way, a tuple is a generalization of std::pair. It is basically a way to store heterogeneous items as, well, a pair. Tuples make me wonder what the advantage is over a vector of structs besides everyone in 2011 (C++11) having forgotten C by then. I guess there are a bunch of helper functions and so on; though interestingly many seem to have been removed for C++20. Oops!

It looks like pair is basically a struct: template<class T1,class T2> struct pair; Anyway, if you’re using pair<blah,blah> X, you mostly need to know about X.first and X.second. Those are not extraction functions so no parentheses. Also X.swap(), which is a function, might possibly be useful for graphics stuff.

Map

Related to a pair in some subtle way is a map. A very simple demonstration of the most basic map syntax.

#include <iostream>
#include <map>
#include <string>
using namespace std;
int main () {
    map<string,int> piechart;
    piechart["C++"]=38;
    piechart["C"]=43;
    piechart["Python"]=19;
    cout << "C++'s value: " << piechart["C++"] << endl;
    cout << "C's value: " << piechart["C"] << endl;
    cout << "Python's value: " << piechart["Python"] << endl;
}

A nice property of the map container is that it is some kind of a tree that stores values in a way that guarantees the keys to be sorted. It can be used to sort complex data on arbitrary fields by making those fields the key.

Here’s a way to iterate over all the items contained in a map object.

for (std::map<char,int>::iterator it=mymap.begin(); it!=mymap.end(); ++it)
    std::cout << it->first << " => " << it->second << '\n';

Note that if you ask for my_hash[not_really_there] it will create a new pair with a key matching what you asked for and a value of empty (or whatever your default constructor dreams up). If you like exceptions, the my_hash.at(key) will not do this, but it will throw an exception if the key is missing. It could be smart to look for the key first as in something like:

if (my_hash.find(key) != my_hash.end()) cout << my_hash[key] << endl;

Algorithm Functions

The STL algorithms can be so bizarre conceptually and with such baroque syntax that it’s hard to even know what they do. But with a decent example, it all starts to make sense. Here was a project I worked on where I had a simple struct L that contained two variables, x and y. I had them in a vector and I needed them sorted on x but made unique with respect to y. Here’s what I used for that.

#include <algorithm>
void sort_unique(vector<L> &vL) {
    if (vL.size() < 2) return; // No need to bother if there is only one or zero items found.
    std::sort(vL.begin(), vL.end(), [](L a, L b) { return a.x < b.x; }); // Sort.
    vector<L>::iterator unique_resize_iter; // This iterator is needed to resize after confusing removals.
    unique_resize_iter= std::unique(vL.begin(), vL.end(),     // Remove duplicates using...
        [](L a,L b){ return a.y == b.y; });                   // ...this lambda predicate function.
    vL.resize(std::distance(vL.begin(),unique_resize_iter) ); // Repair container so it properly takes effect.
} // End function: sort_unique()

You can read more about this and how its speed compares to the unix command line in this blog post I wrote.

Notable interesting functions include the following.

  • sort

  • merge (sorted ranges)

  • unique

  • replace

  • fill, generate (from a function)

  • for_each

  • reverse

  • min, max, minmax (both!)

  • search, find, find_if, search_n (multiples)

  • random_shuffle, shuffle (choose your own method)

  • set_union, set_intersection, set_difference

There is a whole bunch of stuff like that which can be found in the reference documentation.

Time

auto now= std::chrono::system_clock::now();

Random

Newish C++ has a civilized library for random number generation. To use this fine library, I needed to compile with -std=gnu++11.

#include <random>
std::default_random_engine generator;
std::uniform_int_distribution<int> distribution(0,255);
int rand_red_value= distribution(generator);

This library seems pretty comprehensive. It features different PRNG engines and a bunch of distributions. See the official documentation for details.

Another way I’ve seen is something like this.

#include <time.h>
#include <cstdlib>
int main() {
srand(time(NULL));
int target= rand()%100; // 0-99
std::cout << target << std::endl;
return 0;}

Eigen Library Matrix Operations

Examples of working with Eigen matrices
VectorXd my_vector(2);     // Vertical vector of two elements.
my_vector << 10, 20;       // Comma initializer sets coefficients.
cout << my_vector << endl; // cout prints the vector

MatrixXd my_matrix(2,2);   // Initialize Matrix with 2x2 dimensions.
my_matrix << 1, 2,
             3, 4;         // Set matrix to contain [[1,2],[3,4]].
cout << my_matrix << endl; // cout prints a matrix

my_matrix(1,0) = 11;       // Access by position. 2nd row, 1st column.
my_matrix(1,1) = 12;       // 2nd row, 2nd column
my_matrix.row(i) = my_matrix2.col(i); // Get/set row/col vector.

MatrixXd x
x.setZero(rows, cols);     // Fill with zeros. Also a `setOnes()`.
x.setConstant(rows, cols, value); // Fill with value.
x.setRandom(rows, cols);   // Random values.

MatrixXd my_matrix_t = my_matrix.transpose(); // Transpose.
MatrixXd my_matrix_i = my_matrix.inverse();   // Inverse.
MatrixXd my_mtimesv= my_matrix * my_vector;   // Matrix multiplication.

Here’s a nice polynomial fitting routine which uses Eigen.

double polyeval(Eigen::VectorXd coeffs, double x) {
  double result = 0.0;
  for (int i = 0; i < coeffs.size(); i++) {result += coeffs[i]*pow(x, i);}
  return result;
}

Eigen::VectorXd polyfit(Eigen::VectorXd xvals, Eigen::VectorXd yvals, int order) {
  assert(xvals.size() == yvals.size());
  assert(order >= 1 && order <= xvals.size() - 1);
  Eigen::MatrixXd A(xvals.size(), order + 1);
  for (int i = 0; i < xvals.size(); i++) {
    A(i, 0) = 1.0;
  }
  for (int j = 0; j < xvals.size(); j++) {
    for (int i = 0; i < order; i++) {
      A(j, i + 1) = A(j, i) * xvals(j);
    }
  }
  auto Q = A.householderQr();
  auto result = Q.solve(yvals);
  return result;
}

Eigen::VectorXd xvals(6);
Eigen::VectorXd yvals(6);
xvals << 9.261977, -2.06803, -19.6663, -36.868, -51.6263, -66.3482;
yvals << 5.17,     -2.25,    -15.306,  -29.46,  -42.85,   -57.6116;
auto coeffs= polyfit(xvals,yvals,3);
std::cout<< "Y(16)=" << polyeval(coeffs,16) << endl;

This excellent resource explains a low impact way to do "Cubic Spline interpolation in C++ ".

Makefile

Here’s a very simple Makefile that can be used on very simple C++ programming tasks.

ALLSRCS:= $(wildcard *.cc)
ALLEXEC:= $(ALLSRCS:.cc=)
.PHONY:all clean
all: $(ALLEXEC)
%: %.cc
    g++ -o $@ $<
clean:
    rm $(ALLEXEC)

Profiling

Wondering what the heck is taking so long in your program? You can get hints about what your program spends its time doing.

Do this
    sudo apt-get install linux-tools
    sudo bash -c "echo 0 > /proc/sys/kernel/kptr_restrict"
    perf record ./yourprog --your-opts
    perf report
Get a nice report like this
 18.28%  yourprog  yourprog       [.] Plist::querypoint()                    ▒
 13.85%  yourprog  yourprog       [.] shallowanglecull(Llist*, Tlist*, float,▒
  8.70%  yourprog  yourprog       [.] Llist::querypointA()                   ◆
  7.00%  yourprog  yourprog       [.] Llist::querypointB()                   ▒
  6.73%  yourprog  yourprog       [.] Vector::compareto(Vector)              ▒
  5.76%  yourprog  yourprog       [.] searchlinelist(Plist*, Plist*, Llist*) ▒
  5.69%  yourprog  yourprog       [.] operator==(Vector, Vector)             ▒
  5.55%  yourprog  yourprog       [.] Vector::~Vector()                      ▒
  3.92%  yourprog  yourprog       [.] Tlist::BBinterfere(Llist*)             ▒
  3.59%  yourprog  yourprog       [.] searchtrilist(Plist*, Plist*, Plist*, T▒
  2.96%  yourprog  yourprog       [.] Tlist::querylink()                     ▒
  2.88%  yourprog  yourprog       [.] Llist::queryA()                        ▒
  2.26%  yourprog  yourprog       [.] BBinthelper(float, float, float, float,▒
  1.89%  yourprog  yourprog       [.] Vector::gg_valX()                      ▒
  1.25%  yourprog  yourprog       [.] Llist::querylink()                     ▒
  0.92%  yourprog  yourprog       [.] Tlist::querypointC()                   ▒
  0.91%  yourprog  yourprog       [.] find_matching_pnum(unsigned int, Plist*▒
  0.90%  yourprog  yourprog       [.] Vector::Vector()                       ▒
                ...

Or if that isn’t good enough check out gprof.

Actually this hack is quite clever too. See the other suggestions there too (e.g. Valgrind).

Resources For Optimizing