Skip to content

C&C++

Undefined behaviour

Syntax

declarations specify identifiers, whereas definitions specify objects. An object is defined at the same time it is initialized.

An rvalue is a temporary that does not persist beyond the expression that defines it, such as an intermediate function result which is never stored in a variable.

Data types

There are four classes of integers, the specification

Name Minimal bits Description
char Smallest addressable unit of the machine. It contains CHAR_BIT bits
short 16
int 16
long 32
long long 64

Control flow

The following are able to change the control flow of a program

  • if/else
  • while, for and do{} while () i.e. loops
  • function calls
  • goto i.e. short jumps
  • setjmp()/longjmp()/getcontext()/setcontext() i.e. long jumps
  • interrupts and signals
  • threads

Structs

Formatting

modifier Type Conversion
"hh" char integer
"h" short integer
"" signed,unsigned integer
"l" long integer
"ll" long long integer
"j" intmax_t, ``uintmax_t integer
"z" size_t integer
"t" ptrdiff_t integer
"L" long double floating point
flag meaning conversion
"#" alternate form "aAeEfFgGoxX"
"0" zero padding numeric
"-" left adjustment any
" " space for positive number signed
"+" explicit sign for positive number signed

Preprocessor

Value categories

Constructor

CPP reference

There are two differente ways to create an object

Time t (12, 0, 0);
Time* t = new Time(12, 0, 0);

the first allocates the object on the stack, the latter on the heap (src).

Take in mind that if you want to use the default constructor, you cannot write

Time t();

because would pass as a function declaration, you have to use

Time t;

See this answer from stackoverflow.

Also, when you use a statement like

Time t = Time(12, 0, 0);

in reality, under the hood, the constructor is called of T for the right hand side and then the copy constructor for the assignment to the left hand side.

Default constructor

A default constructor is a constructor that either has no parameters, or if it has parameters, all the parameters have default values.

If no user-declared constructors of any kind are provided for a class type (struct, class, or union), the compiler will always declare a default constructor as an inline public member of its class.

Copy constructor

It's in the form Class(const Class&).

Inheritance

It's possible to have multiple parent classes.

Virtual functions

The importance of virtual keyword is that allows for runtime polymorphism, i.e., it tells the compiler to resolve the function call at runtime.

From here

The virtual specifier specifies that a non-static member function is virtual and
supports dynamic dispatch. It may only appear in the decl-specifier-seq of the
initial declaration of a non-static member function (i.e., when it is declared
in the class definition).

If some member function vf is declared as virtual in a class Base, and some
class Derived, which is derived, directly or indirectly, from Base, has a
declaration for member function with the same

name
parameter type list (but not the return type)
cv-qualifiers
ref-qualifiers

Then this function in the class Derived is also virtual (whether or not the
keyword virtual is used in its declaration) and overrides Base::vf (whether or
not the word override is used in its declaration).

Base::vf does not need to be accessible or visible to be overridden. (Base::vf
can be declared private, or Base can be inherited using private inheritance. Any
members with the same name in a base class of Derived which inherits Base do not
matter for override determination, even if they would hide Base::vf during name
lookup.)

To be noted that this specifier has to be applied to the base class, it's the derived class that is affected though.

  • https://stackoverflow.com/questions/2391679/why-do-we-need-virtual-functions-in-c

Virtual base class

It's possible to indicate virtual for the parent class during the declaration of a subclass. This means that

For each distinct base class that is specified virtual, the most derived object
contains only one base class subobject of that type, even if the class appears
many times in the inheritance hierarchy (as long as it is inherited virtual
every time).

Visibility

They exist three keyword

  • public: anyone can access
  • protected: only class and subclasses can access
  • private: only the class in which is defined can access

but also exists

  • friend: allows to specify methods or attributes that can access private properties

Copying, moving, constant and references

By default, when you pass a class as an argument of a function, the copy constructor is called for that class; to avoid that overhead you can use a const reference.

An rvalue is a temporary that does not persist beyond the expression that defines it, such as an intermediate function result which is never stored in a variable.

Operators overloading

Templates

template<typename T>
class Node {
public:
 ...
}

The special expression template<> is called template specialization and allows customizing the template code for a given set of template arguments.

Pointers-to-members

These allow to refer to non-static members of class objects (including functions).

#include <iostream>
using namespace std;

class X {
public:
  int a;
  void f(int b) {
    cout << "The value of b is "<< b << endl;
  }
};

int main() {

  // declare pointer to data member
  int X::*ptiptr = &X::a;

  // declare a pointer to member function
  void (X::* ptfptr) (int) = &X::f;

  // create an object of class type X
  X xobject;

  // initialize data member
  xobject.*ptiptr = 10;

  cout << "The value of a is " << xobject.*ptiptr << endl;

  // call member function
  (xobject.*ptfptr) (20);
}

The pointer to member operators .* and ->* are used to bind a pointer to a member of a specific class object. Because the precedence of () (function call operator) is higher than .* and ->*, you must use parentheses to call the function pointed to by ptf.

Iterators

Mutables

Interfaces

Pratically a class with only virtual functions.

class Entity {
public:
    virtual std::string getName() = 0;
};

Strings

C++ has the C well known char* with the same behaviour; the "standard" way of using strings in C++ is by the std::string class. Obviously you usually do something like this when coding

void some_function(std::string);

int main() {
    ...
    some_function("foobar");
    ...
}

take in mind that "foobar" is in a readonly memory, under the hood it's converted to std::string copying its content.

Find substring

It exists a special value std::string::npos, from the documentation

This is a special value equal to the maximum value representable by the type size_type. The exact meaning depends on context, but it is generally used either as end of string indicator by the functions that expect a string index or as the error indicator by the functions that return a string index.

std::string::size_type indexU = mOpcode.find('u');

bool isUpper = (indexU != std::string::npos);
int value = 0xbad1d34;
std::cout << std::setfill('0') <<  std::setw(8) << std::hex << value << std::endl;

IO

#include <ifstream>

std::ifstream source("file.auaua", std::ios::in);

while (true) {
    char line[21];

    source.getline(line, 20);

    if (source.fail()) {
        break;
    }
    ...
}

Exceptions

#include <stdexcept>

class DivideDyZero : public runtime_error {
    public:
        DivideDyZero() :
         runtime_error("divide by zero exception") {}
};

void whatever() {
    ...
    try{
        ...
    } catch (DivideDyZero & err) {
        std::cerr << err.what() << std::endl;
    } catch (...) {
        std::cerr << "Catch all" << std::endl;
    }
    ...
}

PIMPL

Idiom to break compilation dependencies.

  • https://www.bfilipek.com/2018/01/pimpl.html
  • https://en.cppreference.com/w/cpp/language/pimpl

Logging

A easy way to add logging in a C++ project is to use plog, you can easily add it as a submodule

#include <plog/Log.h> /* this for all the code that needs the PLOG_* stuff */
#include <plog/Init.h> /* this only for the initialization */
#include <plog/Formatters/TxtFormatter.h>
#include <plog/Appenders/ColorConsoleAppender.h>

int main() {

    /* initialization */
    static plog::ColorConsoleAppender<plog::TxtFormatter> consoleAppender(plog::streamStdErr);
    plog::init(plog::verbose, &consoleAppender);

    /* code */

    PLOG_INFO << "reading source file '" << argv[1] << "'";
    /* code after */
}