Jethro's Braindump

C++ Language

What is C++

C++ is a compiled language. For a program to run, its source text has to be processed by a compiler, producing object files, which are combined by a linker yielding an executable program. An executable program is created for a specific hardware/system combination, and is not portable.

The ISO C++ standard defines 2 kinds of entities:

  1. Core language features, such as built-in types and loops
  2. Standard-library components, such as containers (vector and map) and IO operations

C++ is statically typed: the type of each entity must be known to the compiler at its point of use.

References vs Pointers

A reference is similar to a pointer, except that you don’t need to use a prefix * to access the value referred to by the reference. In addition, a reference cannot be made to refer to a different object after its initialization.

int count_x(const char* p, char x) {
  if (p == nullptr) return 0;
  int count = 0;
  for (; *p != 0; ++p) {
    if (*p == x) {
  return count;

C++ Guidelines

Follow the guidelines:

Use General {} style declarations

int i1 = 7.8; // i1 becomes 7
int i2 {7.8}; // error: floating-point to integer conversion

The old = style is traditional and dates back to C. Conversions that lose information, are allowed and implicitly applied. These are the price paid for C compatibility.

Use non-member begin and end

non-member begin and end supports more containers, such as arrays.

vector<int> v;
int a[100];

// C++98
sort(v.begin(), v.end());
sort(&a[0], &a[0] + sizeof(a)/sizeof(a[0]));

// C++11
sort( begin(v), end(v) );
sort( begin(a), end(a) );

Lambda functions

variables get passed through the square brackets.

const int factor = 2;

std::for_each(myVec.begin(), myVec.end(), [factor](int& elem){
  elem *= factor;


using is like typedef, but has less quirks.

using Month = int;

class Date {
    // ...
    Month month() const;  // do
    int month();          // don't
    // ...

avoid endl

The endl manipulator is mostly equivalent to ‘\n’ and “\n”; as most commonly used it simply slows down output by doing redundant flush()s. This slowdown can be significant compared to printf-style output.

Prefer using STL array or vector instead of a C array

C arrays are less safe, and have no advantages over array and vector. For a fixed-length array, use std::array, which does not degenerate to a pointer when passed to a function and does know its size. Also, like a built-in array, a stack-allocated std::array keeps its elements on the stack. For a variable-length array, use std::vector, which additionally can change its size and handles memory allocation.

On Namespacing

How do you properly use namespaces in C++? - Stack Overflow


Resource Acquisition Is Initialization or RAII, is a C++ programming technique which binds the life cycle of a resource that must be acquired before use (allocated heap memory, thread of execution, open socket, open file, locked mutex, disk space, database connection—anything that exists in limited supply) to the lifetime of an object.

The basic idea is that class destructors are always called when a particular instance of an object goes out of scope. This allows for automatic releasing of resources that will never be referenced.

For shared_ptr, the class object contains a pointer to the object, and a reference count for the number of pointers with access to the object at the pointer. Once this reference count hits 0, the object is released.

For unique_ptr, there is no reference count within the class. once this unique_ptr goes out of scope, the object at the pointer is released. For this reason, unique_ptr are more lightweight than shared_ptr, and cannot be copied. unique_ptr can only be moved.

Array Decaying

It’s said that arrays “decay” into pointers. A C++ array declared as int numbers [5] cannot be re-pointed, i.e. you can’t say numbers = 0x5a5aff23. More importantly the term decay signifies loss of type and dimension; numbers decay into int* by losing the dimension information (count 5) and the type is not int [5] any more.

cin/cout vs scanf/printf

cin/cout is actually faster; but C++ slows it down to sync it with C-style io. If using only one style (cin), you can achieve greater IO speed with:


Smart pointers

Here’s a summary of smart-pointers and their semantics. value_ptr is not in the stdlib, but is available as a C++ library.

Figure 1: Tabular summary of smart pointers

Figure 1: Tabular summary of smart pointers


The main advantage of shared pointers is that, we should not worry about calling delete or cleaning the memory in an explicit manner. The shared pointer will take care of it once it goes out of scope. To create a shared_ptr, use make_shared. It’s fast in memory allocation compared to new.

class Sample {
  Sample() { cout << "Constructor make_shared" << endl; }
  ~Sample() { cout << "Destructor make_shared" << endl; }
int main() {
  shared_ptr<Sample> sp = make_shared<Sample>();
  return 0;


Like shared_ptr<>, there is no need to call delete or clean the memory in an explicit manner. The unique pointer will take care of it once it goes out of scope. shared_ptr<> maintains reference counts where more than one shared_ptr<> can refer to a single object.

This is prevented by unique_ptr<> and the reason behind naming it as unique. In unique_ptr<>, one and only one unique_ptr<> has the ownership of the Object and manages its lifetime.


In unique_ptr, std::move is used to transfer the ownership from one unique_ptr to another, which is otherwise not possible.

For shared_ptr, std::move prevents the increment and immediate decrement of the reference count, making it an optimization. It’s not strictly necessary.


not_null is available in GSL, and with compile-time guarantees that a pointer is not null.

Books to read


Links to this note