Skip to content

Latest commit

 

History

History
293 lines (237 loc) · 7.34 KB

cpp-cheat-sheet.md

File metadata and controls

293 lines (237 loc) · 7.34 KB

C++ cheatsheet

Compile and Run

run cpp file on command line (with g++ compiler)

g++ -Wall -std=c++14 textfile.cpp
//	- Wall: turn all warnings on
//	std=c++14: set standart
//	textfile.cpp: set output file

Alternatives for multiple files

g++ -Wall helloworld-helper.cpp helloworld.cpp -o compiled_file

g++ *.cpp -o compiled_file

Afterwards run ./compiled_file

To setup vscode debugger for multiple .cpp files, check that "args" in tasks.json of the workspace config match the following:

Click to expand!
{
    "tasks": [
        {
            "type": "cppbuild",
            "label": "C/C++: g++ build active file",
            "command": "/usr/bin/g++",
            "args": [
                "-g",
                "${fileDirname}/*.cpp",
                "-o",
                "${fileDirname}/${fileBasenameNoExtension}"
            ],
            "options": {
                "cwd": "${fileDirname}"
            },
            "problemMatcher": [
                "$gcc"
            ],
            "group": {
                "kind": "build",
                "isDefault": true
            },
            "detail": "Task generated by Debugger."
        }
    ],
    "version": "2.0.0"
}

import header and helper functions

use following three files:

Click to expand!
  1. hpp header file numbers.hpp
// numbers.hpp
#pragma once  
// To make sure you don't declare the function more than once by including the header multiple times.
// alternatively use 
    // ifndef HEADERVAR   
    // #define HEADERVAR

#include <iostream>
#include <vector>

using namespace std;

void printNumbers(vector<int> numbers);
vector<int> addNumbers(vector<int> &numbers);
    // #endif
  1. helper function numbers-functions.cpp
// numbers-functions.cpp
#include "numbers-header.hpp"

void printNumbers(vector<int> numbers){
    if (numbers.size() == 0)
        cout << "[] - the list is empty" << endl;
    else {
        cout << "[ ";
        for (auto num: numbers)
            cout << num << " ";
        cout << "]" << endl;
    }
}
vector<int> addNumbers(vector<int> &numbers){
    int num_to_add {};
    cout << "Enter an integer to add to the list: ";
    cin >> num_to_add;
    numbers.push_back(num_to_add);
    cout << num_to_add << " added" << endl;
    return numbers;
  1. include numbers.hpp in main file, but not numbers-functions.cpp! Compile and run main.cpp and numbers-functions.cpp, the linker will link the compiled binary files.
#include "numbers-header.h"

int main() {
    printNumbers(numbers);
    numbers = addNumbers(numbers);
}

Coding

safe way of variable initialisation int catch_error{"abc"} initialize local static variable (retains the value over multiple function calls (like a global variable, but on a local scope) static int i{5000};

dynamic memory allocation and deallocation

    size_t size{0};
    double *temp_ptr {nullptr};
    cout << "How much memory to allocate dynamically? ";
    cin >> size;
    
    temp_ptr = new double[size];    // allocate the storage on the heap
    cout << temp_ptr << endl;       // use it
    delete [] temp_ptr;             // release it

for loop by value:

for (const auto num: numbers) // &num to pass by reference
    std::cout << num << std::endl;
}

for loop by reference:

for (const auto &num: numbers) // &num to pass by reference
    std::cout << num << std::endl;
}

####Raw pointers

Always initialize them to avoid wild pointers!

int val{3};
int *ptr = &val;
// alternative with dynamic memory allocation
int *ptr = new int{3}
// don't forget to destroy dynamically allocated memory if not needed anymore!
delete ptr

####Smart pointers

Avoid new keywords! #include <memory> to use smart pointers

#####Unique Pointers

Use as default smart pointer.

They do not allow two unique pointers to point to the same memory. → No copying possible → move instead of assignment

E.g. initialization and move semantics:

  std::unique_ptr<Test> t3;
  t3 = std::move(t1);

Initialize with make_unique auto song = std::make_unique<Test>("abba", "acdc");

E.g. unique pointer pointing to Base class, initialized with adress to a Derived class object (constructor arguments in parenthesis).

std::unique_ptr<Base> a1 = std::make_unique<Derived>("Moe", 5000);

Pass to function

auto int_ptr = std::make_unique<int>();
func(*int_ptr);
void func(int &i) return i++;

#####Shared Pointers Use if more complex memory management needed than unique pointers allow.

Several pointers pointing to the same object possible. They achieve it by introducing a pointer count. The pointer is deallocated only if no pointers are pointing to that memory anymore. → Can also be copied → More similar to raw pointes

ptr.use_count() can be used to determine how many shared pointers point to the object.

// std::shared_ptr<int> p1 {new int {100} }; Unefficient!
// More efficient initialization:
std::shared_ptr<Base> ptr = std::make_shared<Base>(100);
std::cout << "count:"<< ptr.use_count (); 	
ptr.reset();	// decrement the use_count; ptr is nulled out

#####Weak Pointers

  • Few use cases (e.g. avoid cyclic reference that prohibits deletion --> solution: make one of the pointers a weak pointer)
  • Always created from a shared pointer.
  • Points to object on the heap.
  • Does not participate in owning relationship → Doesnt change use_count()

Object-oriented programming

Inheritence: models a "is a" relationship, e.g. student "is a" person. Composition: models a "has a" relationship, e.g. person "has an" account

Rule of thumb: Prefer modelling the system with composition over inheritence, because inheritence adds more complexity.

Use public inheritence to model is-a relationships --> most common Use private or protected inheritance to model has-a relationships --> not covered

Only use inheritence if it is appropriate!

input and output

import for std input/output

#include <iostream>
using namespace std;

std output cout << "Enter your favorite number" << endl;

std input std::cin >> favorite_number;

string declaration in cpp

#include <string> // add `using namespace std;` if necessary
string test = "Some text";
cout << test << endl;

To output objects of user-defined classes, use operator overloading for that class (in its .cpp). E.g.:

std::ostream &operator<<(std::ostream &os, const Account &account) {
    os <<  "Account balance: " << account.balance;
    return os;
}

compound datatypes

create an 1d-array --> fixed size giving the length explicitly int numbers[4]{0, 1, 2, 3, 4} giving the length implicitly int numbers[]{0, 1, 2, 3, 4} // initialize all elements to 3.14 double arr[4] = {3.14};

create a vector (non fixed sized)

#include <vector>
using namespace std;
vector <int> examples(100, 98, 95, 93);

index the 5th vector element examples.at(4) = 80; adding value 80 at the end of vector examples.push_back(80); indexing last element of vector examples.at(examples.size()-1) = 1000; multidimensional vector

vector <vector<int>> movie_ratings 
{   
    {1, 2, 3, 4},
    {1, 2, 4, 4},
    {1, 3, 4, 5}
};

Loop through all vector elements:

std::vector<int> numbers{1,2,3}
for (const auto num: numbers) // &num to pass by reference
    std::cout << num << std::endl;
}