All keywords from R to Z

You can check the part 1 and part 2 before or after reading this one.

R-S

T

U-Z


R

  • register: Hints to the compiler to place the object in the processor’s register. Deprecated in C++17. See: cppreference/register
int main() {
    register int x = 10; // Maybe it is placed in the register for faster access.
}
struct A {
    int x = 10;
};

int main() {
    A a;
    int* i = reinterpret_cast<int*>(&a);
    std::cout << *i; // Prints: 10
}
  • return: This keyword let’s you return from a function, returning the expression. See: cppreference/return
int foo() {
    return 10;
}

int main() {
    std::cout << foo(); // Prints: 10
}

S

  • short: Integer type used for natural numbers with size of 2 bytes. See: cppreference/short
short x = 10;
std::cout << sizeof(x); // 2 bytes.
  • signed: Indicates that the type is represented as signed, which means that can represent negative values. See: cppreference/signed
signed int x = -20;
std::cout << sizeof(std::string); // Prints: 32
  • static: Life duration specifier. It tells that the variable or function must live since the begining until the end of the program. For this reason, an static function or variable inside a custom type, is defined outside the type. See: cppreference/static
struct A {
    static int x = 10;
    static int foo() {
        return 42
    }
}

int main() {
    std::cout << A::x << " | " << A::foo(); // Prints: 10 | 42
}
static_assert(sizeof(int) == 8, "Size of int must be 4"); // error: static assertion failed: Size of int must be 4
  • static_cast: Converts between types using a combination of implicit and user-defined conversions. See: cppreference/static_cast
float z = 10.5;
std::cout << static_cast<int>(z); // Prints: 10
struct A {}
  • switch: The switch statement redirect the flow based on different cases defined for the value. See: cppreference/switch
enum class Enum {A, B, C};

switch(Enum::B) {
    case Enum::A: 
        std::cout << "Enum::A";
        break;
    case Enum::B: 
        std::cout << "Enum::B"; // <-- Jumps here.
        break;
    case Enum::C: 
        std::cout << "Enum::C";
        break;
}

T

template<class T>
foo(T t) {}

int main() {
    foo(10);
    foo("Hello World");
    foo(10.5);
}
  • this: The this keyword is a pointer to the class itself. Technically, it is passed at every member function but is hidden from the user as a syntax sugar. See: cppreference/this
struct A {
    int x = 10;
    void foo() {
        std::cout << x << " | " << this->x; // Prints: 10 | 10
        std::cout << sizeof(this); // Prints: 8 (pointer in x86_64)
        std::cout << sizeof(*this); // Prints: 4 (size of the member values)
    }
}
  • thread_local: Thread storage duration. Each thread has it’s own copy of the value. The value it’s allocated when the thread is created and deallocated when it’s destroyed. It prevents data races. See: cppreference/thread_local
thread_local int x = 0;
int y = 0;

void f(){
    x = x + 1; // It is okey since it is thread_local.
    y = y + 1; // Accumulate by every thread.
    std::cout << "x = " << x << '\n'; // X is always 1.
    std::cout << "y = " << y << '\n'; // Y value its random between 1 or 2
}

int main(){
    std::thread t1(f);
    std::thread t2(f);
    t1.join();
    t2.join();
}
try {
    std::string("abc").substr(10); // throws std::length_error
}
catch (const std::exception& e) {
    std::cout << e.what() << '\n';
    throw;   // rethrows the exception object of type std::length_error
}
bool b = false;
std::cout << b; // Prints "1"
try {
    std::string("abc").substr(10); // throws std::length_error
} catch (const std::exception& e) { // reference to the base of a polymorphic object
    std::cout << e.what(); // information from length_error printed
}
typedef myInt = int;

// Those two declarations are equivalent.
myInt x = 10;
int y = 10;
  • typeid: Returns information for a type. It is dependent on compiler implementation. The output is without demangling it. See: cppreference/typeid
struct Base {}; // non-polymorphic
struct Derived : Base {};
 
struct Base2 { virtual void foo() {} }; // polymorphic
struct Derived2 : Base2 {};
 
int main() {
    int myint = 50;
    std::string mystr = "string";
    double *mydoubleptr = nullptr;
 
    std::cout << "myint has type: " << typeid(myint).name() << '\n'
              << "mystr has type: " << typeid(mystr).name() << '\n'
              << "mydoubleptr has type: " << typeid(mydoubleptr).name() << '\n';
 
    // std::cout << myint is a glvalue expression of polymorphic type; it is evaluated
    const std::type_info& r1 = typeid(std::cout << myint); // side-effect: prints 50
    std::cout << '\n' << "std::cout<<myint has type : " << r1.name() << '\n';
 
    // std::printf() is not a glvalue expression of polymorphic type; NOT evaluated
    const std::type_info& r2 = typeid(std::printf("%d\n", myint));
    std::cout << "printf(\"%d\\n\",myint) has type : " << r2.name() << '\n';
 
    // Non-polymorphic lvalue is a static type
    Derived d1;
    Base& b1 = d1;
    std::cout << "reference to non-polymorphic base: " << typeid(b1).name() << '\n';
 
    Derived2 d2;
    Base2& b2 = d2;
    std::cout << "reference to polymorphic base: " << typeid(b2).name() << '\n';
 
    try {
        // dereferencing a null pointer: okay for a non-polymorphic expression
        std::cout << "mydoubleptr points to " << typeid(*mydoubleptr).name() << '\n'; 
        // dereferencing a null pointer: not okay for a polymorphic lvalue
        Derived2* bad_ptr = nullptr;
        std::cout << "bad_ptr points to... ";
        std::cout << typeid(*bad_ptr).name() << '\n';
    } catch (const std::bad_typeid& e) {
         std::cout << " caught " << e.what() << '\n';
    }
}

// Output:
myint has type: i
mystr has type: NSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEE
mydoubleptr has type: Pd
50
std::cout<<myint has type : NSt3__113basic_ostreamIcNS_11char_traitsIcEEEE
printf("%d\n",myint) has type : i
reference to non-polymorphic base: 4Base
reference to polymorphic base: 8Derived2
mydoubleptr points to d
bad_ptr points to...  caught std::bad_typeid
template<typename T>
void foo(T t) { }

U

  • union: A union is a special class type that can hold only one of its non-static data members at a time. Its size os always the bigger data member. See: cppreference/union
union U {
    int x;
    double y;
    bool b;
};

int main() {
    U u {10}; // U::x is now the active member.
    std::cout << u.x << '\n'; // 10
    std::cout << u.y << '\n'; // UB: uninitialized value.
    u.y = 10.5; // U::y is now the active member.
    std::cout << u.y << '\n'; // 10.5
    std::cout << u.x << '\n'; // UB: uninitialized value.
    u.b = true; // U::b is now the active member.
    std::cout << u.b << '\n'; // True

    std::cout << sizeof(U); // 8 bytes (because the double data member)
}
  • unsigned: Type without sign, only positives values. Asigning negative values produce overflow. See: cppreference/unsigned
unsigned int x = -1;
std::cout << x; // 4294967295 ( 2^32 - 1)  
  • using: Introduces a name that it is defined elsewhere. Can be types or namespaces. See: cppreference/using
using namespace std;
using std::string;

cout << "cout without std namespace";
string str = "RRM Programming";

V

  • virtual: Can be used in non static member functions and anotate that the function can perform dynamic dispatching. The compiler will generate a virtual tables, also known as VTables and will jump at runtime to the specific type function. The override specifier is optional. See: cppreference/virtual
class Base {
    public:
        Base() {}
        virtual void foo() = 0;
};

class Derived : public Base {
    public:
        Derived() {}
        virtual void foo() /*override*/ {
            std::cout << "Derived::foo()";
        };
};
  • void: Indicates that a function return nothing (void). It can also be used as a function parameter. See: cppreference/void
void foo(void) {
    std::cout << "I don't return anything";
}

int main() {
    foo();
}
  • volatile: Volatile accesses cannot be optimized out or reordered with another visible side effect that is sequenced-before or sequenced-after the volatile access. This makes volatile objects suitable for communication with a signal handler, but not with another thread of execution. See: cppreference/volatile
volatile int x = 10; // The compiler can not optimize this variable out.

W

wchar_t c = 'a';
std::cout << sizeof(c); // 4 bytes
  • while: A while-loop is a loop that iterates until the condition is equal to false. See: cppreference/while
int x = 0;
while ( x < 3 ) {
    std::cout << x << '\n';
    x++;
}

// Output:
0
1
2

X

  • xor: Performs a bitwise xor operation. It’s equivalent to ^. See: cppreference/xor
auto b1 = 0xb11110000;
auto b2 = 0xb00101111;
 
auto b3 = b1 xor b2;
std::cout << std::hex << b3 << '\n'; // 11011111
  • xor_eq: Performs a bitwise xor operation with the value itself. Equivalent to ^=. See: cppreference/xor_eq
auto b1 = 0xb11110000;
auto b2 = 0xb00101111;
 
std::cout << std::hex << b1 << '\n'; // b11110000
b1 xor_eq b2;
std::cout << std::hex << b1 << '\n'; // b11011111

That’s all 😉