// MathJax

Source Builds

$ cmake --version
$ make --version
$ g++ --version

 

 

[G++][No Linked Program]: File: main.cpp

|-- main.cpp
$ g++ main.cpp # compile + assemble + liking
$ g++ main.cpp -o program # compile + assemble + liking

$ g++ -c main.cpp # compile + assemble
$ g++ main.o -o program # linking

 

[G++][No Linked Program]: File: main.cpp / module.cpp / module.hpp

|-- main.cpp
|-- module.cpp
|-- module.hpp
$ g++ -c main.cpp
$ g++ -c module.cpp
$ g++ main.o module.o -c program

 

[G++][Linked Program]: File: main.cpp / module.cpp / module.hpp

|-- main.cpp
|-- module.cpp
|-- module.hpp
$ g++ -fPIC -o module.o -c module.cpp
$ g++ -shared -o libmodule.so module.o
$ g++ -o program main.cpp -L. -lmodule -I.

 

[Make][No Linked Program]: File: main.cpp / module.cpp / module.hpp / Makefile

|-- main.cpp
|-- module.cpp
|-- module.hpp
|-- Makefile
# Makefile
PREFIX ?= .
BIN_INSTALL_DIR = $(PREFIX)/bin
INCLUDE_INSTALL_DIR = $(PREFIX)/include

all: program

program : module.o main.o
    g++ module.o main.o -o program

main.o : main.cpp module.cpp
    g++ -c main.cpp

module.o : module.cpp module.hpp
    g++ -c module.cpp

install: program
    mkdir -p $(BIN_INSTALL_DIR)
    mkdir -p $(INCLUDE_INSTALL_DIR)
    cp program $(BIN_INSTALL_DIR)
    cp *.hpp $(INCLUDE_INSTALL_DIR)
    @echo "Installed program to $(BIN_INSTALL_DIR)"
    @echo "Installed header files to $(INCLUDE_INSTALL_DIR)"

clean:
    rm -f program *.o

.PHONY: all install clean
$ make
$ make install PREFIX=.
$ make clean

 

[Make][Linked Program]: File: main.cpp / module.cpp / module.hpp / Makefile

|-- main.cpp
|-- module.cpp
|-- module.hpp
|-- Makefile
# Makefile
PREFIX ?= .
LIB_INSTALL_DIR = $(PREFIX)/lib
BIN_INSTALL_DIR = $(PREFIX)/bin
INCLUDE_INSTALL_DIR = $(PREFIX)/include

all: program

program: main.o module.o libmodule.so
    g++ -o program main.o -L. -lmodule

libmodule.so: module.o
    g++ -shared -o libmodule.so module.o

module.o: module.cpp module.hpp
    g++ -Wall -fPIC -c -o module.o module.cpp

main.o: main.cpp module.hpp
    g++ -Wall -fPIC -c -o main.o main.cpp

install: program libmodule.so
    mkdir -p $(BIN_INSTALL_DIR)
    mkdir -p $(INCLUDE_INSTALL_DIR)
    mkdir -p $(LIB_INSTALL_DIR)
    cp program $(BIN_INSTALL_DIR)
    cp *.hpp $(INCLUDE_INSTALL_DIR)
    cp libmodule.so $(LIB_INSTALL_DIR)
    @echo "Installed program to $(BIN_INSTALL_DIR)"
    @echo "Installed header files to $(INCLUDE_INSTALL_DIR)"
    @echo "Installed libmodule.so to $(LIB_INSTALL_DIR)"

clean:
    rm -f program libmodule.so *.o

.PHONY: all install clean
$ make
$ make install PREFIX=.
$ make clean

 

[CMake][No Linked Program]: File: main.cpp / CMakeLists.txt: No Linked Program

|-- main.cpp
|-- CMakeLists.txt
|-- build
# CMakeLists.txt
cmake_minimum_required(VERSION 3.11)
project(Name LANGUAGES CXX)

set(CMAKE_CXX_COMPILER "/usr/bin/g++")
set(CMAKE_CXX_COMPILER_VERSION 9)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)

message(STATUS "C++ Compiler: ${CMAKE_CXX_COMPILER}")
message(STATUS "C++ Compiler Version: ${CMAKE_CXX_COMPILER_VERSION}")
message(STATUS "C++ Standard: ${CMAKE_CXX_STANDARD}")
message(STATUS "Install Path: ${CMAKE_INSTALL_PREFIX}")

add_executable(program main.cpp)
install(TARGETS program DESTINATION bin) # -DCMAKE_INSTALL_PREFIX
./build$ cmake -S.. -B. -DCMAKE_INSTALL_PREFIX=.. && make && make install
./build$ cmake -S.. -B. -DCMAKE_INSTALL_PREFIX=.. && cmake --build . --target install
$ cmake -S. -Bbuild -DCMAKE_INSTALL_PREFIX=. && cmake --build build --target install

 

[CMake][No Linked Program]: File: main.cpp / module.cpp / module.hpp / CMakeLists.txt

|-- main.cpp
|-- module.cpp
|-- module.hpp
|-- CMakeLists.txt
|-- build
# CMakeLists.txt
cmake_minimum_required(VERSION 3.11)
project(Name LANGUAGES CXX)

set(CMAKE_CXX_COMPILER "/usr/bin/g++")
set(CMAKE_CXX_COMPILER_VERSION 9)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)

message(STATUS "C++ Compiler: ${CMAKE_CXX_COMPILER}")
message(STATUS "C++ Compiler Version: ${CMAKE_CXX_COMPILER_VERSION}")
message(STATUS "C++ Standard: ${CMAKE_CXX_STANDARD}")
message(STATUS "Install Path: ${CMAKE_INSTALL_PREFIX}")

add_executable(program main.cpp module.cpp)
install(TARGETS program DESTINATION bin) # -DCMAKE_INSTALL_PREFIX
install(FILES module.h DESTINATION include) # -DCMAKE_INSTALL_PREFIX
./build$ cmake -S.. -B. -DCMAKE_INSTALL_PREFIX=.. && make && make install
./build$ cmake -S.. -B. -DCMAKE_INSTALL_PREFIX=.. && cmake --build . --target install
$ cmake -S. -Bbuild -DCMAKE_INSTALL_PREFIX=. && cmake --build build --target install

 

[CMake][Linked Program]: File: main.cpp / module.cpp / module.hpp / CMakeLists.txt: Linked Program

|-- main.cpp
|-- module.cpp
|-- module.hpp
|-- CMakeLists.txt
|-- build
# CMakeLists.txt
cmake_minimum_required(VERSION 3.11)
project(Name LANGUAGES CXX)

set(CMAKE_CXX_COMPILER "/usr/bin/g++")
set(CMAKE_CXX_COMPILER_VERSION 9)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

message(STATUS "C++ Compiler: ${CMAKE_CXX_COMPILER}")
message(STATUS "C++ Compiler Version: ${CMAKE_CXX_COMPILER_VERSION}")
message(STATUS "C++ Standard: ${CMAKE_CXX_STANDARD}")
message(STATUS "Install Path: ${CMAKE_INSTALL_PREFIX}")

add_executable(program main.cpp module.cpp)
install(TARGETS program DESTINATION bin) # -DCMAKE_INSTALL_PREFIX
install(FILES module.hpp DESTINATION include) # -DCMAKE_INSTALL_PREFIX

add_library(library SHARED module.cpp)
install(TARGETS library DESTINATION lib) # -DCMAKE_INSTALL_PREFIX
./build$ cmake -S.. -B. -DCMAKE_INSTALL_PREFIX=.. && make && make install
./build$ cmake -S.. -B. -DCMAKE_INSTALL_PREFIX=.. && cmake --build . --target install
$ cmake -S. -Bbuild -DCMAKE_INSTALL_PREFIX=. && cmake --build build --target install

 

 

 

 

G++ Version

#include <iostream>
using namespace std;

int main() {
  cout << "__cplusplus = " << __cplusplus << endl;
  return 0;
}
$ g++ -std=c++11 main.cpp
$ g++ -std=c++14 main.cpp
$ g++ -std=c++17 main.cpp
$ g++ -std=c++2a main.cpp

 

 

G++ Compiler

sudo add-apt-repository ppa:ubuntu-toolchain-r/test
sudo apt-get update

sudo apt-get install g++-4.9 gcc-4.9
sudo apt-get install g++-5 gcc-5
sudo apt-get install gcc-7 g++-7
sudo apt-get install gcc-8 g++-8
sudo apt-get install gcc-9 g++-9
sudo apt-get install gcc-11 g++-11
sudo update-alternatives --remove-all gcc 
sudo update-alternatives --remove-all g++

sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-4.9 49
sudo update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-4.9 49

sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-5 50
sudo update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-5 50

sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-7 70
sudo update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-7 70

sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-8 80
sudo update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-8 80

sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-9 90
sudo update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-9 90

sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-11 110
sudo update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-11 110

sudo update-alternatives --config gcc
sudo update-alternatives --config g++

 

 

 

 


Built-in Keywords

#ifndef A_H
#define A_H
#include <iostream>
#include <string>
#include "lib.h"

using namespace std;

using int16_t = int;
typedef int int16_t;

// class
class A {};

// arrays
int array_int[];
float array_float[];
char array_char[];
string array_string[];

#endif

int main() {
}

 

library

#include <istream>
#include "*headerfile.h"

 

 

template

#include <iostream>
using namespace std;

template<typename T>
T func(T a, T b) {
    return a + b;
};

template<typename T1, typename T2, typename T3>
void func(T1 a, T2 b, T3 c) {
    cout << a << endl;
    cout << b << endl;
    cout << c << endl;
};


int main(){
    int int_a = 0;
    int int_b = 1;
    int ret_int;
    ret_int = func<int>(int_a, int_b); cout << ret_int << endl;

    float float_a = 3.14;
    float float_b = 3.14;
    float ret_float;
    ret_float = func<float>(float_a, float_b); cout << ret_float << endl;

    string string_a = "hello";
    string string_b = "world";
    string ret_string;
    ret_string = func<string>(string_a, string_b); cout << ret_string << endl;

    int a = 0;
    float b = 3.14;
    string c = "hello, world";
    func<int, float, string>(a, b, c);

    return 0;
}
#include <iostream>
using namespace std;

template<typename T>
class Structure {
    private:
        T attr_a;
        T attr_b;
    public:
        explicit Structure(T a, T b): attr_a{a}, attr_b{b}{};
        ~Structure(){};
};

int main(){
    Structure<int> s1{0, 1};
    Structure<float> s2{3.14, 3.14};
    Structure<string> s3{"hello", "world"};
    return 0;
}

 

 

typedef

#include <iostream>
using namespace std;

template <typename T>
class TemplateClass{
    T member ;
    public:
        explicit TemplateClass(T param):member{param}{};
        ~TemplateClass(){};
};

typedef TemplateClass<int> IntTemplate;
typedef TemplateClass<float> FloatTemplate;
typedef TemplateClass<string> StringTemplate;

int main() {
    IntTemplate a{0};
    FloatTemplate b{3.14};
    StringTemplate c{"string"};
    return 0;
}

 

 

namespace

#include <iostream>
using namespace std;

// function namespace
namespace Function {

    void func(int x, float y) {
        cout << x << y << endl;
    };

    namespace A {
        void func(int x, float y) {
            cout << x << y << endl;
        };

        namespace a {
            void func(int x, float y) {
                cout << x << y << endl;
            };
        };
    };
};

int main() {
    // datatype namespace: alias
    typedef int integer;
    using floating_point = float;
    integer x = 1; floating_point y = 3.14;

    Function::func(x, y);
    Function::A::func(x, y);
    Function::A::a::func(x, y);

    using Function::A::a::func;
    func(x, y);

    namespace target_scope = Function::A::a;
    target_scope::func(x,y);

    using namespace Function;
    func(x, y);
    A::func(x, y);
    A::a::func(x, y);
    return 0;
}

 

 

scope resolution operator(::)

#include <iostream>
using namespace std;

class Class {
    public:
        struct MemberStruct{
            int a = 1;
        };

        class MemberClass{
            public: int a = 1;
        };

        static void member_func(){
            cout << "hello world!" << endl;
        };
};

template <typename T>
class TemplateClass {
    public:
        struct Member{
            T a = 1;
        };

        static void member_func(){
            cout << "hello world!" << endl;
        };
};

int main(){
    ::Class::member_func();
    ::Class::MemberStruct cm_struct;
    ::Class::MemberClass cm_class;
    ::std::cout << cm_struct.a << ::std::endl;
    ::std::cout << cm_class.a << ::std::endl;


    ::TemplateClass<void>::member_func();
    ::TemplateClass<int>::Member tcm_struct;
    ::std::cout << tcm_struct.a << ::std::endl;
}

 

 

 

 


Variable and Operator and Function

Variable

  • Variable(1)
    • Normal Variable
    • Pointer Variable
    • Reference Variable
  • Variable(2)
    • Compile Time Variable
    • Run-Time Variable

 

Variable Initialization

  • Initialization
    • copy initialization: =
    • direct initialization: ()
    • uniform initialization: {}
      • Cast to type is not allowed.
#include <iostream>
using namespace std;

// variable initialization
int main() {
        int a = 5; cout << a << endl; // copy initialization
        int b(5);  cout << b << endl; // direct initialization
        int c{5};  cout << c << endl; // uniform initialization
        int d{};   cout << d << endl; // default initialization to 0
                                          
        // Literal
        double pi = 3.141592; // 
        double av = 6.02e23; //
        double el = 1.6e-19; //

        return 0;
}
#include <iostream>
using namespace std;

class UniformInit {
    int a;
    int b;
    public:
        explicit UniformInit(int a, int b):a{a}, b{b}{};
        ~UniformInit(){};
};

template <typename T>
void init_args(std::initializer_list<T> args){
    for (const auto& i: args) {};
};

int main() {
    UniformInit uni_init_obj1{1, 2};
    UniformInit uni_init_obj2 = UniformInit{1, 2};

    std::initializer_list<int> uni_init_list = {1,2,3,4,5};
    init_args(uni_init_list);
    init_args({1,2,3,4,5});
}

 

 

Operator

Bit operator

#include <iostream>
using namespace std;

int main() {
    // & operator(logic)
    int num1 = 4; // 00000000 00000000 00000000 00000100
    int num2 = 8; // 00000000 00000000 00000000 00001000
    int num3 = num1 & num2; // 00000000 00000000 00000000 00000000 > 0

    int num4 = 1; // 00000000 00000000 00000000 00000001
    int num5 = 3; // 00000000 00000000 00000000 00000011
    int num6 = num4 & num5; // 00000000 00000000 00000000 00000001 > 1

    // | operator(logic)
    int num7 = 4; // 00000000 00000000 00000000 00000100
    int num8 = 1; // 00000000 00000000 00000000 00000001
    int num9 = num7 | num8; // 00000000 00000000 00000000 00000101 > 5

    // ^ operator(logic)
    int num10 = 15; // 00000000 00000000 00000000 00001111
    int num11 = 7;  // 00000000 00000000 00000000 00000111
    int num12 = num10 ^ num11; // 00000000 00000000 00000000 00001000 > 8

    // ~ operator(logic)
    int num13 = 15; // 00000000 00000000 00000000 00001111
    int num14 = ~num13; // 11111111 11111111 11111111 11110000 > 00000000 00000000 00000000 00010000 > -16

    // << operator(shift)
    int num15 = 10; // 00000000 00000000 00000000 00001010
    int shift1 = num15 << 1; // 00000000 00000000 00000000 00010100 > 20
    int shift2 = num15 << 2; // 00000000 00000000 00000000 00101000 > 40
    int shift3 = num15 << 3; // 00000000 00000000 00000000 01010000 > 80

    // >> operator(shift)
    int num16 = -16;
    int shift4 = num16 >> 1; // -8
    int shift5 = num16 >> 2; // -4
    int shift6 = num16 >> 3; // -2

    return 0;
}

 

 

Function

Main Function

#include <iostream>
using namespace std;

int main(int argc, char** argv){
    cout << argc << " arguments are passed:" << endl;
    for(int i = 0; i < argc; i++){
        cout << argv[i] << endl;
    }
}
./program argument1 argument2 argument3

 

Function Basic

#include <iostream>
using namespace std;

// called function: parameters: x,y
int func(int x, int y) {
        return x + y;
}

// caller function
int main() {
        int reval;
        int x = 1; int y = 1;
		
        reval = func(x, y); cout << reval << endl; // arguments: x,y
        
        return 0;
}

 

Function Parameter and Argument

  • pass by value
  • pass by reference
  • pass by address
    • function
    • array
    • class
#include <iostream>
using namespace std;

void func1(int x, float y) {x = 0; y = 0.0;};
void func2(int& x, float& y) {x = 0; y = 0.0;}
void func3(int* x, float* y) {*x = 0; *y = 0.0;};
void func4(const int x, const float y) {};
void func5(const int& x, const float& y) {};
void func6(const int* x, const float* y) {
    int z = 0; float zf = 0;
    x = &z; y = &zf;
};
void func7(const int* const x, const float* const y) {};

int main() {
        int x = 1; float y = 3.14;
        func1(x, y); func1(x, 3.14); func1(1, y); func1(1, 3.14); // local
        cout << x << y << endl;

        x = 1; y = 3.14;
        func2(x, y); // nonlocal
        cout << x << y << endl;

        x = 1; y = 3.14;
        func3(&x, &y); // nonlocal
        cout << x << y << endl;

        x = 1; y = 3.14;
        func4(x, y); // local
        cout << x << y << endl;

        x = 1; y = 3.14;
        func5(x, y); // local
        cout << x << y << endl;

        x = 1; y = 3.14;
        func6(&x, &y); // local
        cout << x << y << endl;

        x = 1; y = 3.14;
        func7(&x, &y); // local
        cout << x << y << endl;

        return 0;
}
#include <iostream>
using namespace std;

int main() {
        int x = 0; int x1 = 1; int x2 = 2; int x3 = 3; int x4 = 4; int x5 = 5;
        const int y = 0; const int y1 = 1; const int y2 = 2; const int y3 = 3; const int y4 = 4; const int y5 = 5;

        // normal variable
        x = 1; x = 2; x = 3; x = 4; x = 5; x = 0;

        // pointer variable
        int* i_ptr;
        i_ptr = &x; i_ptr = &x1; i_ptr = &x2; i_ptr = &x3; i_ptr = &x4; i_ptr = &x5; // Changing Reference
        *i_ptr = x1; *i_ptr = x2; *i_ptr = x3; *i_ptr = x4; *i_ptr = x5; // Changing Dereference: Variable
        *i_ptr = 1; *i_ptr = 2; *i_ptr = 3; *i_ptr = 4; *i_ptr = 5; // Changing Deference: Constant

        const int* ci_ptr;
        ci_ptr = &x; ci_ptr = &x1; ci_ptr = &x2; ci_ptr = &x3; ci_ptr = &x4; ci_ptr = &x5; // Reference
        ci_ptr = &y; ci_ptr = &y1; ci_ptr = &y2; ci_ptr = &y3; ci_ptr = &y4; ci_ptr = &y5; // Reference

        // constant pointer variable
        int* const i_cptr = &x;
        *i_cptr = x1; *i_cptr = x2; *i_cptr = x3; *i_cptr = x4; *i_cptr = x5; // Changing Dereference: Variable
        *i_cptr = 1; *i_cptr = 2;*i_cptr = 3;*i_cptr = 4;*i_cptr = 5; // Chaning Dereference: Constant

        const int* const ci_cptr = &y;

        // reference variable
        int& iref = x;
        iref = x; iref = x1; iref = x2; iref = x3; iref = x4; iref = x5;
        iref = y; iref = y1; iref = y2; iref = y3; iref = y4; iref = y5;
        iref = 1; iref = 2; iref = 3; iref = 4; iref = 5;

        const int& ciref_i = x; x = 1; x = 2; x = 3; x = 4; x = 5; x = 0;
        const int& ciref_ci = y;


        return 0;
}

 

Function Parameter and Argument by Array, Function, Class

#include <iostream>
using namespace std;

void func(int arr1[], int* arr2){};

int main() {
    int arr[] = {1, 2, 3, 4, 5};
    func(arr, arr);
    return 0;
}
#include <iostream>
using namespace std;

void param1(){};
bool param2(){return true;};
int param3(){return 0;};

void param4(){};
bool param5(bool arg){return true;};
int param6(int arg){return 0;};

void func1(void (*param1)(), bool (*param2)(), int (*param3)()){};
void func2(void (*param1)(), bool (*param2)(bool arg), int (*param3)(int arg)){};

int main() {
    func1(param1, param2, param3);
    func2(param4, param5, param6);
    return 0;
}
#include <iostream>
using namespace std;

class Date {
    public:
        int year;
        int month;
        int day;

        Date(int c_year, int c_month, int c_day):year{c_year}, month{c_month}, day{c_day} {};
        ~Date() {};
};

void func(Date date){};

int main() {
    Date date{2020, 1, 1};
    func(date);
    return 0;
}

 

Function Return

  • return by value
    • local variable
  • return by reference
    • class, struct 
  • return by address
    • array, pointer
#include <iostream>
using namespace std;


int func1(int x) {
    x += 1;
    return x;
}

int func2(int& x) {
    x += 1;
    return x;
}

int& func3(int& x) {
    x += 1;
    return x;
}

int* func4(int& x) {
    x += 1;
    return &x;
}

int main() {
    int x1 = 0; int x2 = 0; int x3 = 0; int x4 = 0;

    int ret1 = func1(x1); cout << "int func(int x): " << x1 << endl;
    int ret2 = func2(x2); cout << "int func(int& x): " << x2 << endl;
    int& ret3 = func3(x3); cout << "int& func(int& x): " << x3 << endl;
    int* ret4 = func4(x4); cout << "int* func(int& x): " << x4 << endl;

    ret1 = 10; cout << "x = " << x1 << endl; // x = 0
    ret2 = 10; cout << "x = " << x2 << endl; // x = 1
    ret3 = 10; cout << "x = " << x3 << endl; // x = 10
    *ret4 = 10; cout << "x = " << x4 << endl; // x = 10

    return 0;
}
#include <iostream>
using namespace std;


int func1(int* x) {
    x += 1;
    return *x;
}

int* func2(int* x) {
    *x += 1;
    return x;
}

int& func3(int* x) {
    *x += 1;
    return *x;
}

int main() {
    int x1 = 0; int x2 = 0; int x3 = 0;
    int* ptr1 = &x1; int* ptr2 = &x2; int* ptr3 = &x3;

    int ret1 = func1(ptr1); cout << "int func(int x): " << x1 << endl;
    int* ret2 = func2(ptr2); cout << "int* func(int* x): " << x2 << endl;
    int& ret3 = func3(ptr3); cout << "int& func(int* x): " << x3 << endl;

    ret1 = 10; cout << "x = " << x1 << endl; // x = 0
    *ret2 = 10; cout << "x = " << x2 << endl; // x = 10
    ret3 = 10; cout << "x = " << x3 << endl; // x = 10

    return 0;
}

 

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

class Functor {
    public:
        void operator()(){
        };
        int operator()(int param){
            return param;
        };
};

int func1(int param){return param;};
int* func2(int* param){return param;};
int& func3(int& param){return param;};
int& func2c(int* param){return *param;};
int* func3c(int& param){return &param;};

Functor& func4(Functor& param){return param;};
auto& func5(Functor& param){return param;};
std::function<int(int)> func6(int (*param)(int arg)){return param;};

typedef int (*fptr1)(int);
fptr1 func7(int (*param)(int arg)){return param;};

using fptr2 = int (*)(int);
fptr2 func8(int (*param)(int arg)){return param;};

int main() {
    int var = 1;
    int arr[] = {1,2,3,4,5};
    Functor func_obj;
    int (*fptr_p)(int) = func1;

    // param: var | arr
    int ret1 = func1(var);
    int* ret2 = func2(arr);
    int& ret3 = func3(var);
    int& ret2c = func2c(arr);
    int* ret3c = func3c(var);

    // param: func_obj
    Functor ret4_1 = func4(func_obj);
    auto ret4_2 = func4(func_obj);
    Functor ret5_1 = func5(func_obj);
    auto ret5_2 = func5(func_obj);

    // param: fptr_p
    std::function<int(int)> ret6_1 = func6(fptr_p);
    std::function<void(int)> ret6_2 = func6(fptr_p);
    auto ret6_3 = func6(fptr_p);

    fptr1 ret7_1 = func7(fptr_p);
    auto ret7_2 = func7(fptr_p);
    std::function<int(int)> ret7_3 = func7(fptr_p);
    std::function<void(int)> ret7_4 = func7(fptr_p);

    fptr2 ret8_1 = func8(fptr_p);
    auto ret8_2 = func8(fptr_p);
    std::function<int(int)> ret8_3 = func8(fptr_p);
    std::function<void(int)> ret8_4 = func8(fptr_p);

    return 0;
}

 

 

Function Namespace

#include <iostream>
using namespace std;

namespace Alphabet {

    void func(int x, float y) {
        cout << x << y << endl;
    };

    namespace A {
        void func(int x, float y) {
            cout << x << y << endl;
        };

        namespace a {
            void func(int x, float y) {
                cout << x << y << endl;
            };
        };
    };

    // C++ 17
    namespace B {
        void func(int x, float y) {
            cout << x << y << endl;
        };
    };
    namespace B::b {
        void func(int x, float y) {
            cout << x << y << endl;
        };
    };

};

int main() {
    int x = 1; float y = 3.14;
    Alphabet::func(x, y);
    Alphabet::A::func(x, y);
    Alphabet::B::func(x, y);
    Alphabet::A::a::func(x, y);
    Alphabet::B::b::func(x, y);

    using Alphabet::A::a::func;
    func(x, y);

    namespace target_scope = Alphabet::A::a;
    target_scope::func(x,y);

    using namespace Alphabet;
    func(x, y);
    A::func(x, y);
    A::a::func(x, y);


    return 0;
}

 

 

Anonymous functions: Lambda expression

#include <iostream>
using namespace std;

int main() {
    []() -> void {};
    []() -> void {return;};
    []() -> int {return 0;};
    [](int x) -> int {return x;};

    int a = 1; int b = 2;
    [a, b]() -> int {return a + b;};
    [a, b](int x) -> int {return a + b + x;};
    [a, b](int x) -> int {return a + b + x;}(10);
    [a, b](int x, int y) -> int {return a + b + x;}(10, 100);
    ([a, b](int x, int y) -> int {return a + b + x;})(10, 100);

    auto add = [](int x, int y) -> int {return x + y;};
    auto sub = [](int x, int y) -> int {return x - y;};
    auto mul = [](int x, int y) -> int {return x*y;};
    auto div = [](int x, int y) -> int {return x/y;};
    add(2, 1); sub(2, 1); mul(2, 1); div(2, 1);

    int c = 0;
    [&c]() -> void { c += 1; cout << c << endl;}(); // reference for c
    [&]() -> void { a+=2; b+=1; c+=2; cout << a << b << c << endl;}(); // reference for all variables

    [c]() -> void { cout << c << endl;}(); // value c
    [=]() -> void { cout << a << b << c << endl;}(); // all values 

    return 0;
}

 

 

 

 


 

Data Types

  • primary: integer, character, boolean, floating point, double floating point, void, wide character
  • derived: function, array([]), vector([]), pointer(*), reference(&)
  • user defined: class, structure, union, enum, typedef
#include <iostream>
using namespace std;
 
int main() {
    cout << "Size of char : " << sizeof(char) << endl;
    cout << "Size of int : " << sizeof(int) << endl;
    cout << "Size of long : " << sizeof(long) << endl;
    cout << "Size of float : " << sizeof(float) << endl;
    cout << "Size of double : " << sizeof(double) << endl;
 
    return 0;
}

 

type alias: using, typedef

#include <iostream>

using namespace std;
typedef int Integer;

int main() {
        Integer integer = 1; cout << integer << endl;

        return 0;
}
#include <iostream>

using namespace std;
using Integer = int;

int main() {
        Integer integer = 1; cout << integer << endl;

        return 0;
}

 

 

type casting

  • static_cast
  • dynamic_cast
  • const_cast
  • reinterpret_cast
#include <iostream>
#include <string>
#include <typeinfo>

using namespace std;

int main(){
        float x = 3.14;
        int a; int b; int c;

        cout << "Value) x = " << to_string(x) << endl;
        cout << " Type) type: " << typeid(x).name() << endl << endl;

        a = x; // Implicit
        cout << "Value) a = " << to_string(a) << endl;
        cout << " Type) type: " << typeid(a).name() << endl << endl;

        b = (int)x; // Explicit
        cout << "Value) b = " << to_string(b) << endl;
        cout << " Type) type: " << typeid(b).name() << endl << endl;

        c = static_cast<int>(x); // Casting
        cout << "Value) c = " << to_string(c) << endl;
        cout << " Type) type: " << typeid(c).name() << endl << endl;

        return 0;
}

 

type 

//

 

Initialization

//

 

 

 

User Defined Data Type: class, structure, union, enum, typedef

typedef

typedef long int32_t;
typedef short int16_t;
typedef char int8_t;
typedef int myinteger;
typedef char *mystring;
typedef void (*myfunc)();

myinteger i;   // is equivalent to    int i;
mystring s;    // is the same as      char *s;
myfunc f;      // compile equally as  void (*f)();

 

Initializer List

#include <iostream>
using namespace std;

int main(){
    for(char element: {'a', 'b', 'c'}){
        cout << element << endl;
    }

    initializer_list<char> il = {'a', 'b', 'c'};
    for(char element: il){
        cout << element << endl;
    }

    return 0;
}

 

Enum V.S. Enum Class

#include <iostream>
using namespace std;

enum EnumDataType {
    zero, one, two
};

enum class EnumClassDataType {
    zero, one, two
};

int main() {
    EnumDataType E1(zero);
    EnumDataType E2(one);
    EnumDataType E3(two);

    EnumDataType E4 = zero;
    EnumDataType E5 = one;
    EnumDataType E6 = two;

    EnumDataType E7 = static_cast<EnumDataType>(0);
    EnumDataType E8 = static_cast<EnumDataType>(1);
    EnumDataType E9 = static_cast<EnumDataType>(2);

    EnumClassDataType EC1(EnumClassDataType::zero);
    EnumClassDataType EC2(EnumClassDataType::one);
    EnumClassDataType EC3(EnumClassDataType::two);

    EnumClassDataType EC4 = EnumClassDataType::zero;
    EnumClassDataType EC5 = EnumClassDataType::one;
    EnumClassDataType EC6 = EnumClassDataType::two;

    EnumClassDataType EC7 = static_cast<EnumClassDataType>(0);
    EnumClassDataType EC8 = static_cast<EnumClassDataType>(1);
    EnumClassDataType EC9 = static_cast<EnumClassDataType>(2);
}

 

Class V.S. Struct

#include <iostream>
using namespace std;

struct StructDataType { 
        // members are public by default
        int year;
        int month;
        int day;
};

class ClassDataType {
        // members are private by default
       	public:
            int year;
            int month;
            int day;
};

int main() {
        StructDataType A{2024, 1, 1}; cout << A.year << A.month << A.day << endl;
        ClassDataType B{2024, 1, 1};  cout << B.year << B.month << B.day << endl;        
}


Namespace for Enum, Class

#include <iostream>
using namespace std;

enum class NewD0 { a, b, c };
class NewD1 { public: int a=0; int b=1; int c=2; explicit NewD1(){;};};
class NewD2 { public: enum class ED{ a, b, c}; explicit NewD2(){;};};
namespace ROOT {
    namespace SUB {
        class NewD3 { public: enum class ED { a, b, c}; explicit NewD3(){;};};
    };
};

void obj0_param_func(NewD0 param){cout << static_cast<int>(param) <<endl;};
void obj1_param_func(NewD1 param){cout << param.a + param.b + param.c << endl;};
void obj2_param_func(NewD2::ED param){cout << static_cast<int>(param) << endl;};
void obj3_param_func(ROOT::SUB::NewD3::ED param){cout << static_cast<int>(param) << endl;};

int main() {
    NewD0 var0 = NewD0::a;
    obj0_param_func(var0);

    NewD1 var1 = NewD1{};
    obj1_param_func(var1);

    NewD2 var2 = NewD2{};
    NewD2* ptr2; *ptr2 = var2;
    obj2_param_func(var2.ED::a);
    obj2_param_func(ptr2->ED::a);

    ROOT::SUB::NewD3 var3 = ROOT::SUB::NewD3{};
    obj3_param_func(var3.ED::a);

    return 0;
}

 

 

Derived: function, array([]), vector([]), pointer(*), reference(&)

Array

Array address and value

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

int main(){
    int arr[] = {1,2,3,4,5};

    cout << arr[0] << endl;
    cout << arr[1] << endl;
    cout << arr[2] << endl;
    cout << arr[3] << endl;
    cout << arr[4] << endl;

    cout << &arr[0] << endl;
    cout << &arr[1] << endl;
    cout << &arr[2] << endl;
    cout << &arr[3] << endl;
    cout << &arr[4] << endl;

    // array begin
    cout << *(&arr[0] + 0) << endl;
    cout << *(&arr[0] + 1) << endl;
    cout << *(&arr[0] + 2) << endl;
    cout << *(&arr[0] + 3) << endl;
    cout << *(&arr[0] + 4) << endl;

    // array end - 1
    cout << *(&arr[4] - 4) << endl;
    cout << *(&arr[4] - 3) << endl;
    cout << *(&arr[4] - 2) << endl;
    cout << *(&arr[4] - 1) << endl;
    cout << *(&arr[4] - 0) << endl;

    // diff pointer
    ptrdiff_t ptrdiff0 = &arr[0] - &arr[0]; cout << arr[ptrdiff0] << endl;
    ptrdiff_t ptrdiff1 = &arr[1] - &arr[0]; cout << arr[ptrdiff1] << endl;
    ptrdiff_t ptrdiff2 = &arr[2] - &arr[0]; cout << arr[ptrdiff2] << endl;
    ptrdiff_t ptrdiff3 = &arr[3] - &arr[0]; cout << arr[ptrdiff3] << endl;
    ptrdiff_t ptrdiff4 = &arr[4] - &arr[0]; cout << arr[ptrdiff4] << endl;

    // add pointer
    ptrdiff_t ptrdiff0_ = 0; cout << *(&arr[0] + ptrdiff0_) << endl;
    ptrdiff_t ptrdiff1_ = 1; cout << *(&arr[0] + ptrdiff1_) << endl;
    ptrdiff_t ptrdiff2_ = 2; cout << *(&arr[0] + ptrdiff2_) << endl;
    ptrdiff_t ptrdiff3_ = 3; cout << *(&arr[0] + ptrdiff3_) << endl;
    ptrdiff_t ptrdiff4_ = 4; cout << *(&arr[0] + ptrdiff4_) << endl;

    return 0;
}

 

Array declaration

#include <iostream>
using namespace std;

int main(){
    int arr[] = {100, 200, 300, 400, 500};

    int* ptr1 = arr;
    int* ptr2 = &arr[0];
    cout << ptr1 << endl;
    cout << ptr2 << endl;
    cout << static_cast<void*>(ptr1) << endl;
    cout << static_cast<void*>(ptr2) << endl;

    for(int* ptr = arr; ptr < arr + 5; ptr++){
        cout << *ptr << ' ';
    } cout << endl;


    return 0;
}
#include <iostream>
using namespace std;

int main(){
    char arr[] = {'a', 'b', 'c', 'd', 'e'};

    char* ptr1 = arr;
    char* ptr2 = &arr[0];
    cout << ptr1 << endl;
    cout << ptr2 << endl;
    cout << static_cast<void*>(ptr1) << endl;
    cout << static_cast<void*>(ptr2) << endl;

    for(char* ptr = arr; ptr < arr + 5; ptr++){
        cout << *ptr << ' ';
    } cout << endl;


    return 0;
}

 

Array dimension

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


int main(){
    // [1D Array] Stack: Array of pointers
    int arr1d[3]; arr1d[0] = 1; arr1d[1] = 2; arr1d[2] = 3;
    int arr1d_a[3]; arr1d_a[0] = 1; arr1d_a[1] = 2; arr1d_a[2] = 3;
    int arr1d_b[3] = {1,2,3};
    int arr1d_c[] = {1,2,3};
    int arr1d_d[5] = {1,2,3}; // 1,2,3,0,0

    int* parr1d[3] = {nullptr, nullptr, nullptr};
    int (*parr1d_a)[3] = &arr1d_a;
    int (*parr1d_b)[3] = &arr1d_b;
    int (*parr1d_c)[3] = &arr1d_c;
    int (*parr1d_d)[5] = &arr1d_d;

    // [1D Array] Heap: Array of pointers
    int* hp_arr1d_a = new int[3]; delete[] hp_arr1d_a;
    int* hp_arr1d_b = new int[3](); delete[] hp_arr1d_b;
    int* hp_arr1d_c = new int[3]{}; delete[] hp_arr1d_c;
    int* hp_arr1d_d = new int[3]{1,2,3}; delete[] hp_arr1d_d;

    int** hp_parr1d_a = new int*[3]; delete[] hp_parr1d_a;
    int** hp_parr1d_b = new int*[3](); delete[] hp_parr1d_b;
    int** hp_parr1d_c = new int*[3]{}; delete[] hp_parr1d_c;
    int** hp_parr1d_d = new int*[3]{nullptr, nullptr, nullptr}; delete[] hp_parr1d_d;

    // [2D Array]: Stack: Array of pointers
    int arr2d[2][2]; arr2d[0][0] = 0; arr2d[0][1] = 1; arr2d[1][0] = 2; arr2d[1][1] = 3;
    int arr2d_a[2][2]; arr2d_a[0][0] = 0; arr2d_a[0][1] = 1; arr2d_a[1][0] = 2; arr2d_a[1][1] = 3;
    int arr2d_b[2][2] = {{0,1}, {2,3}};
    int arr2d_c[][2] = {{0,1}, {2,3}};
    int arr2d_d[][5] = {{0,1,2,3,4}, {5,6,7,8,9}};

    int* parr2d[2][2] = {{nullptr, nullptr}, {nullptr, nullptr}};
    int (*parr2d_a)[2][2] = &arr2d_a;
    int (*parr2d_b)[2][2] = &arr2d_b;
    int (*parr2d_c)[2][2] = &arr2d_c;
    int (*parr2d_d)[2][5] = &arr2d_d;

    // [2D Array]: Heap: Array of pointers
    int (*hp_arr2d_a)[3] = new int[2][3]; delete[] hp_arr2d_a;
    auto hp_arr2d_b = new int[2][3]; delete[] hp_arr2d_b;


    return 0;
}

 

Array Usage

#include <iostream>
#include <array>
#include <algorithm>
using namespace std;


int main(){
    // Create Array
    int bltn_arr_a[] = {1, 2, 3};
    float bltn_arr_b[] = {3.14, 1.1, 2.7};
    string bltn_arr_c[] = {"3.14", "1.1", "2.7"};
    char bltn_arr_d[] = "ABC";

    array<int, 3> std_arr_a = {1,2,3};
    array<float, 3> std_arr_b = {3.14, 1.1, 2.7};
    array<string, 3> std_arr_c = {"3.14", "1.1", "2.7"};
    array<char, 3> std_arr_d = {'A', 'B', 'C'};

    // Update Array
    std_arr_a.at(0) = 3; std_arr_a.at(1) = 2; std_arr_a.at(2) = 1;
    bltn_arr_a[0] = 3; bltn_arr_a[1] = 2; bltn_arr_a[2] = 1;

    // Sort Array
    sort(std_arr_a.begin(), std_arr_a.end()); // forward
    sort(std_arr_a.rbegin(), std_arr_a.rend()); // backward:reverse

    // Read Array
    for(int i = 0; i < sizeof(bltn_arr_a)/sizeof(int); i++) {
            cout << bltn_arr_a[i] << " " << bltn_arr_b[i] << " " << bltn_arr_c[i] << " " << bltn_arr_d[i] << endl;
            cout << std_arr_a[i] << " " << std_arr_b[i] << " " << std_arr_c[i] << " " << std_arr_d[i] << endl;
    }

    for(int i = 0; i < std_arr_a.size(); i++) {
        cout << std_arr_a[i] << endl;
    }
    for(auto& element: bltn_arr_a){
        cout << element << endl;
    }
    for(auto& element: std_arr_a){
        cout << element << endl;
    }

    return 0;
}

 

Vector

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

int main() {
    vector<int> vec = {10, 20, 30, 40, 50};

    for (size_t i = 0; i < vec.size(); ++i) {
        cout << "index: " << i << endl;
        cout << "value: " << vec[i] << endl;
    }

    return 0;
}

 

Pointer and Reference

#include <iostream>
using namespace std;

int main() {
        // pointers for non constant variables
        char c = 'c'; cout << c << endl;
        int i = 0; cout << i << endl;
        float f = 3.14; cout << f << endl;
        double d = 3.141592; cout << d << endl;

        char* c_ptr = &c; cout << c_ptr << endl;
        int* i_ptr = &i; cout << i_ptr << endl;
        float* f_ptr = &f; cout << f_ptr << endl;
        double* d_ptr = &d; cout << d_ptr << endl;

        char* const c_cptr = &c; cout << c_cptr << endl;
        int* const i_cptr = &i; cout << i_cptr << endl;
        float* const f_cptr = &f; cout << f_cptr << endl;
        double* const d_cptr = &d; cout << d_cptr << endl;

        // pointers for constant variables
        const char cc = 'c'; cout << cc << endl;
        const int ci = 0; cout << ci << endl;
        const float cf = 3.14; cout << cf << endl;
        const double cd = 3.141592; cout << cd << endl;

        const char* cc_ptr = &cc; cout << cc_ptr << endl;
        const int* ci_ptr = &ci; cout << ci_ptr << endl;
        const float* cf_ptr = &cf; cout << cf_ptr << endl;
        const double* cd_ptr = &cd; cout << cd_ptr << endl;

        const char* const cc_cptr = &cc; cout << cc_cptr << endl;
        const int* const ci_cptr = &ci; cout << ci_cptr << endl;
        const float* const cf_cptr = &cf; cout << cf_cptr << endl;
        const double* const cd_cptr = &cd; cout << cd_cptr << endl;

        return 0;
}

 

 

Pointer

  • non-constant pointer
    • Variable pointer
      • non-constant variable pointer [base]
      • constant variable pointer
      • null pointer
    • Function pointer
      • void pointer
  • constant pointer
    • variable pointer
      • non-constant variable pointer
      • constant variable pointer [base]
      • null pointer
    • function pointer
      • void pointer

 

Variable Pointer & Reference

#include <iostream>
using namespace std;

int main() {
        int x = 0;

        int* ptr = &x; cout << ptr << endl;
        *ptr = 1;      cout << ptr << endl;

        return 0;
}
#include <iostream>
using namespace std;

int main(){
        int a = 1; // variable
        int* ptr = &a; // pointer variable

        cout << a << endl; // value
        cout << ptr << endl; // integer address

        cout << *ptr << endl; // dereference: value
        cout << &a << endl; // reference: integer address
        cout << &ptr << endl; // reference: ptr pointer address

        return 0;
}
#include <iostream>
using namespace std;

int main(){
        const int a = 1; // variable
        const int* ptr = &a; // pointer variable

        cout << a << endl; // value
        cout << ptr << endl; // integer address

        cout << *ptr << endl; // dereference: value
        cout << &a << endl; // reference: integer address
        cout << &ptr << endl; // reference: ptr pointer address

        return 0;
}
#include <iostream>
using namespace std;

int main() {
    // pointer and reference 
    int a = 5;
    int* const ptr = &a;
    int& ref = a;

    cout << *ptr << endl;
    cout << ref << endl;
    return 0;
}

 

Non-local variable

#include <iostream>
using namespace std;

void pointer_nonlocal(int* x) {*x = 1;}
void reference_nonlocal(int& x) {x = 2;}

int main() {
    int a = 0;

    pointer_nonlocal(&a);  cout << a << endl;
    reference_nonlocal(a); cout << a << endl;

    return 0;
}
#include <iostream>
using namespace std;

void func() {
    static int a = 0;
    a++; cout << a << endl;
}

int main() {
    func();
    func();
    func();
    return 0;
}

 

Void Pointer & Null Pointer

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

int main() {
    bool bool_dt = true;
    int int_dt = 0;
    float float_dt = 3.14;
    double double_dt = 3.141592;
    char char_dt = 'A';

    void* noninit_vptr;
    void* init_vptr = nullptr;

    noninit_vptr = &bool_dt; bool* bool_ptr = static_cast<bool*>(noninit_vptr);
    noninit_vptr = &int_dt; int* int_ptr = static_cast<int*>(noninit_vptr);
    noninit_vptr = &float_dt; float* float_ptr = static_cast<float*>(noninit_vptr);
    noninit_vptr = &double_dt; double* double_ptr = static_cast<double*>(noninit_vptr);
    noninit_vptr = &char_dt; char* char_ptr = static_cast<char*>(noninit_vptr);

    cout << *bool_ptr << endl;
    cout << *int_ptr << endl;
    cout << *float_ptr << endl;
    cout << *double_ptr << endl;
    cout << *char_ptr << endl;

    return 0;
}

 

Memory Allocation: new, delete

#include <iostream>
using namespace std;

int main() {
    int* ptr = new int; // dynamically allocate an integer
    *ptr = 7; // put a value in that memory location
    delete ptr; // return the memory to the operating system.  ptr is now a dangling pointer.
    ptr = nullptr;

    return 0;
}

 

Memory Leak

#include <iostream>
using namespace std;

int main() {
    int value = 5;
    int* ptr = new int; // allocate memory
    delete ptr;         // return memory back to operating system
    ptr = &value;       // reassign pointer to address of value

    return 0;
}

 

Smart Pointer: auto, unique, shared, weak

#include <iostream>
#include <functional>
#include <memory>
using namespace std;

int main() {
    // variable
    int var = int(10);
    
    // pointer
    int* ptr = new int(20); delete ptr; ptr = nullptr;

    // function pointer
    int (*func)(float) = [](float param) -> int {return param;};
    std::function<int(float)> fptr = [](float param) -> int {return param;};

    // smart pointers: unique: memory ownership
    unique_ptr<int> u_sptr(new int(10));

    // smart pointers: shared: reference count
    shared_ptr<int> s_sptr1(new int(10)); {
        shared_ptr<int> s_sptr2 = s_sptr1;
    }

    // smart pointers: weak: circular reference
    struct B;
    struct A {shared_ptr<B> AB_s_sptr;};
    struct B {weak_ptr<A> BA_w_sptr;};

    shared_ptr<A> A_s_sptr(new A());
    shared_ptr<B> B_s_sptr(new B());

    A_s_sptr->AB_s_sptr = B_s_sptr;
    B_s_sptr->BA_w_sptr = A_s_sptr;
    return 0;
}

 

 

Array Pointer & Reference

#include <iostream>
using namespace std;

int main(){
    int arr[3] = {1, 2, 3}; // array: pointer variable
    int* ptr = arr; // pointer variable: point to 0th element of the arr
    int (*aptr)[3] = &arr; // array pointer variable

    cout << "sizeof(arr): " << sizeof(arr) << endl;
    cout << "sizeof(ptr): " << sizeof(ptr) << endl;
    cout << "sizeof(aptr): " << sizeof(aptr) << endl;

    cout << "arr[0]: " << arr[0] << endl; // first value
    cout << "arr[1]: " << arr[1] << endl; // second value
    cout << "arr[2]: " << arr[2] << endl; // third value
    cout << "ptr[0]: " << ptr[0] << endl; // first value
    cout << "ptr[1]: " << ptr[1] << endl; // second value
    cout << "ptr[2]: " << ptr[2] << endl; // third value
    cout << "(*aptr)[0]: " << (*aptr)[0] << ", aptr[0]: " << aptr[0] << endl; // first value & address
    cout << "(*aptr)[1]: " << (*aptr)[1] << ", aptr[1]: " << aptr[1] << endl; // second value & address
    cout << "(*aptr)[2]: " << (*aptr)[2] << ", aptr[2]: " << aptr[2] << endl << endl; // third value & address

    cout << "[Pointer Variables]" << endl;
    cout << "   arr: " << arr << endl; // 0th element address
    cout << "   ptr: " << ptr << endl; // 0th element address
    cout << "  aptr: " << aptr << endl << endl; // 0th element address

    cout << "  *arr: " << *arr << endl; // dereference: first value
    cout << "  *ptr: " << *ptr << endl; // dereference: first value
    cout << " *aptr: " << *aptr << endl << endl; // dereference: 0th element address

    cout << "  &arr: " << &arr << endl; // reference: 0th element address
    cout << "  &ptr: " << &ptr << endl; // reference: ptr pointer address
    cout << " &aptr: " << &aptr << endl << endl; // reference: aptr pointer address: array address

    cout << "[Increment Operator for Pointer Variables]" << endl;
    cout << "  *ptr: " << *ptr << ", ptr: " << ptr << endl; // dereference: 0th element value
    cout << " (*aptr)[0]: " << (*aptr)[0] << ", aptr[0]: " << aptr[0] << endl << endl; // dereference: 0th element value
    
    ptr++;
    cout << " ptr++; *ptr: " << *ptr << ", ptr: " << ptr << endl; // dereference: 1st element value
    cout << " (*aptr)[1]: " << (*aptr)[1] << ", aptr[1]: " << aptr[1] << endl << endl; // dereference: 0th element value
    ptr--;

    ptr++;ptr++;
    cout << " ptr++;ptr++; *ptr: " << *ptr << ", ptr: " << ptr << endl; // dereference: 2nd element value
    cout << " (*aptr)[2]: " << (*aptr)[2] << ", aptr[2]: " << aptr[2] << endl << endl; // dereference: 0th element value
    ptr--;ptr--;

    cout << "  &arr: " << &arr << endl; // reference: 0th element address
    cout << "  &ptr: " << &ptr << endl; // reference: ptr pointer address
    cout << " &aptr: " << &aptr << endl << endl; // reference: aptr pointer address: array address

    return 0;
}

 

 

Function Pointer & Reference

#include <iostream>
using namespace std;

int main() {
    int (*fptr1)();
    int (*fptr2)(int);
    bool (*fptr3)(int, int);
    void (*fptr4)();
    void (*fptr5)(int, int);
    void (*fptr6)(int*);
    void (*fptr7)(int, int*);

    typedef int (*fptr8)();
    typedef int (*fptr9)(int);
    typedef bool (*fptr10)(int, int);
    typedef void (*fptr11)();
    typedef void (*fptr12)(int, int);
    typedef void (*fptr13)(int*);
    typedef void (*fptr14)(int, int*);

    using fptr15 = int (*)();
    using fptr16 = int (*)(int);
    using fptr17 = bool (*)(int, int);
    using fptr18 = void (*)();
    using fptr19 = void (*)(int);
    using fptr20 = void (*)(int*);
    using fptr21 = void (*)(int, int*);

    return 0;
}
#include <iostream>
#include <functional>
using namespace std;

// function pointers
void (*fptr1)(){};
void (*fptr2)(int){};
void (*fptr_p1)();
void (*fptr_p2)(int);
typedef void (*fptr3)();
typedef void (*fptr4)(int);
using fptr5 = void (*)();
using fptr6 = void (*)(int);
std::function<void()> fptr7 {};
std::function<void(int)> fptr8 {};
std::function<void()> fptr_p7;
std::function<void(int)> fptr_p8;


// reference functions
void ref_func1(){};
void ref_func2(int x){};
void ref_func3(){};
void ref_func4(int x){};
void ref_func5(){};
void ref_func6(int x){};
void ref_func7(){};
void ref_func8(int x){};

// main callback function
void funcparam_func1(void (*fptr_p1)(), void (*fptr_p2)(int)){};
void funcparam_func2(fptr3 fptr_p1, fptr4 fptr_p2){};
void funcparam_func3(fptr5 fptr_p1, fptr6 fptr_p2){};
void funcparam_func4(std::function<void()> fptr_p1, std::function<void(int)> fptr_p2){};

int main() {
    fptr_p1 = ref_func1;
    fptr_p2 = ref_func2;
    funcparam_func1(fptr_p1, fptr_p2);
    funcparam_func1(fptr1, fptr2);

    fptr3 fptr_p3 = ref_func3;
    fptr4 fptr_p4 = ref_func4;
    funcparam_func2(fptr_p3, fptr_p4);

    fptr5 fptr_p5 = ref_func5;
    fptr6 fptr_p6 = ref_func6;
    funcparam_func3(fptr_p5, fptr_p6);

    fptr_p7 = ref_func7;
    fptr_p8 = ref_func8;
    funcparam_func4(fptr_p7, fptr_p8);
    funcparam_func4(fptr7, fptr8);


    funcparam_func1(fptr_p1, fptr_p2);
    funcparam_func1(fptr_p3, fptr_p4);
    funcparam_func1(fptr_p5, fptr_p6);

    funcparam_func2(fptr_p1, fptr_p2);
    funcparam_func2(fptr_p3, fptr_p4);
    funcparam_func2(fptr_p5, fptr_p6);

    funcparam_func3(fptr_p1, fptr_p2);
    funcparam_func3(fptr_p3, fptr_p4);
    funcparam_func3(fptr_p5, fptr_p6);

    funcparam_func4(fptr_p1, fptr_p2);
    funcparam_func4(fptr_p3, fptr_p4);
    funcparam_func4(fptr_p5, fptr_p6);
    funcparam_func4(fptr_p7, fptr_p8);
    return 0;
}

 

 

constant function pointer

#include <iostream>
using namespace std;

int func() {
    return 0;
}

int nonconst_func(int x) {
    return x;
}

int main() {
    // allocation(1)
    int (*ptr_noparam)();
    int (*ptr_param)(int);
    ptr_noparam = func; cout << ptr_noparam() << endl;
    ptr_param = nonconst_func; cout << ptr_param(1) << endl;

    // allocation(2)
    int (*ncfptr)() = func; // non-constant function pointer
    int (*const cfptr)() = func; // constant function pointer
    cout << ncfptr() << endl;
    cout << cfptr() << endl;

    int (*fptr)(int) = nonconst_func; // non-constant function pointer
    cout << fptr(5) << endl;
    cout << (*fptr)(5) << endl;

    return 0;
}
//

 

 

Class Pointer: Inheritance & Polymorphism

//

 

 

 


Object Oriented Programming: Class and Struct

OOP Structure

#include <iostream>
using namespace std;

class BaseStructure {
    int year;
    int month;
    int day;

    int* hour;
    int* minute;
    int* second;

    public:
        explicit BaseStructure(int c_year, int c_month, int c_day):year{c_year}, month{c_month}, day{c_day} {
            int* hour = new int{3};
            int* minute = new int{50};
            int* second = new int{20};
        }
        ~BaseStructure() {
            delete hour;
            delete minute;
            delete second;
        }

        BaseStructure& Chaining(){return *this;}

        void setter(int year, int month, int day) {
            this->year = year; this->month = month; this->day = day;
        }
        int get_year() {return year;}
        int get_month() {return month;}
        int get_day() {return day;}

        int method() const {return year + month + day;}
        int core(const BaseStructure& other) { return other.method();}

        int func1() {return 0;}
        int func2() const {return 0;}
        int& func3() {return day;}
        static int func4() {return 0;}
};


int main() {

    BaseStructure A{2025, 1,1};
    A.setter(2024, 1, 1);
    A.get_year(); A.get_month(); A.get_day();

    BaseStructure* obj_ptr;
    obj_ptr = &A;
    obj_ptr->setter(2025, 1, 1);
    obj_ptr->get_year(); obj_ptr->get_month(); obj_ptr->get_day();

    const BaseStructure B{2026, 1,1};
    A.core(B);

    BaseStructure* C = new BaseStructure{2020,1,1};
    delete C;
}

 

Declaration V.S. Definition(Implementation)

#include <iostream>
using namespace std;

class BaseStructure {
    int year;
    int month;
    int day;

    public:
        explicit BaseStructure(int c_year, int c_month, int c_day);
        ~BaseStructure() {};

        BaseStructure& Chaining();

        void setter(int year, int month, int day);
        int get_year();
        int get_month();
        int get_day();

        int method() const;
        int core(const BaseStructure& other);

};

BaseStructure::BaseStructure(int c_year, int c_month, int c_day):year{c_year}, month{c_month}, day{c_day} {};
BaseStructure& BaseStructure::Chaining(){return *this;}
void BaseStructure::setter(int year, int month, int day) {this->year = year; this->month = month; this->day = day;}
int BaseStructure::get_year(){return year;}
int BaseStructure::get_month(){return month;}
int BaseStructure::get_day(){return day;}
int BaseStructure::method() const {return year + month + day;}
int BaseStructure::core(const BaseStructure& other) {return other.method();}

int main() {
        BaseStructure A{2025, 1,1};
        A.setter(2024, 1, 1);
        A.get_year(); A.get_month(); A.get_day();
        
        const BaseStructure B{2025, 1,1};
        A.core(B);
}

 

access specifiers: public, private, protected

#include <iostream>
using namespace std;

class PublicClass {
    public:
        int year;
        int month;
        int day;
};

class PrivateClassA {
    private:
        int year;
        int month;
        int day;

    public:
        explicit PrivateClassA (int c_year, int c_month, int c_day) {
            year = c_year; month = c_month; day = c_day;
        }
};

class PrivateClassB {
    int year;
    int month;
    int day;

    public:
        explicit PrivateClassB (int c_year, int c_month, int c_day) {
            year = c_year; month = c_month; day = c_day;
        }
};


class PrivateClassC {
    int year = 2024;
    int month = 1;
    int day = 1;
};

class PrivateClassD {
    int year = 2024;
    int month = 1;
    int day = 1;

    public:
        explicit PrivateClassD () {}
};


class ProtectedClass {
    protected:
        int year;
        int month;
        int day;

    public:
        explicit ProtectedClass (int c_year, int c_month, int c_day) {
            year = c_year; month = c_month; day = c_day;
        }
};

int main() {
        PublicClass D1{2024, 1, 1};
        PrivateClassA D2{2024, 1, 1};
        PrivateClassB D3{2024, 1, 1};
        PrivateClassC D4{};
        PrivateClassD D5{};
        ProtectedClass D6{2024, 1, 1};
}

 

 

constructor v.s. initialization

#include <iostream>
using namespace std;

class ConstructorA {
    int year;
    int month;
    int day;

    public:
        explicit ConstructorA(int c_year, int c_month, int c_day) {
            year = c_year; month = c_month; day = c_day;
        }
};

class ConstructorB {
    int year;
    int month;
    int day;

    public:
        explicit ConstructorB(int c_year, int c_month, int c_day):year(c_year), month(c_month), day(c_day) {}
};

class ConstructorC {
    int year;
    int month;
    int day;

    public:
        explicit ConstructorC(int c_year, int c_month, int c_day): year{c_year}, month{c_month}, day{c_day} {}
};


int main() {
        ConstructorA D1{2025, 1,1};
        ConstructorA D2(2025, 1,1);
        ConstructorB D3{2025, 1,1};
        ConstructorB D4(2025, 1,1);
        ConstructorC D5{2025, 1,1};
        ConstructorC D6(2025, 1,1);
}
#include <iostream>
using namespace std;

class ConstructorA {
    int year;
    int month;
    int day;

    public:
        explicit ConstructorA(int c_year, int c_month, int c_day): year{c_year}, month{c_month}, day{c_day} {}
        explicit ConstructorA(int c_year, int c_month): year{c_year}, month{c_month}, day{30} {}
};

class ConstructorB {
    int year;
    int month;
    int day;

    public:
        explicit ConstructorB(int c_year, int c_month, int c_day): year{c_year}, month{c_month}, day{c_day} {}
        explicit ConstructorB(int c_year, int c_month): ConstructorB{c_year, c_month, 30} {}
};

class ConstructorC {
    int year;
    int month;
    int day;

    public:
        explicit ConstructorC(int c_year, int c_month, int c_day=30): year{c_year}, month{c_month}, day{c_day} {}
};

int main() {
        ConstructorA D1{2025, 1, 30};
        ConstructorA D2{2025, 1};
        ConstructorB D3{2025, 1, 30};
        ConstructorB D4{2025, 1};
        ConstructorC D5{2025, 1, 30};
        ConstructorC D6{2025, 1};
}

 

#include <iostream>
using namespace std;

class Initialization {
    int year = 2024;
    int quarter{4};
    int month;
    int day;

    public:
        explicit Initialization(int c_month, int c_day):month{c_month}, day{c_day} {}
};

int main() {
        Initialization A{1,1};
}

 

User Interface: Abstract Class: Overriding by Inheritance

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

class Parent {
    int year = 2020;
    int month = 1;
    int day = 1;

    public:
        explicit Parent() {};
        ~Parent() {};

        virtual void print() { cout << to_string(year) + ':' + to_string(month) + ':' + to_string(day) << endl;};
};

class Child: public Parent {
    int year = 2050;
    int month = 1;
    int day = 1;

    public:
        explicit Child() {};
        ~Child() {};

        void print() override { cout << to_string(year) + '-' + to_string(month) + '-' + to_string(day) << endl;};
};

int main() {
    Parent P; P.print();
    Child C; C.print();

    return 0;
}
#include <iostream>
#include <string>
using namespace std;

class Abstract {
    public:
        void common_member_func() { cout << "Abstract" << endl;} ;
        virtual void unique_member_func() = 0 ;
};

class Derived: public Abstract {
    public:
        explicit Derived(){};
        ~Derived(){};

        void unique_member_func() override { cout << "Derived" << endl;};
};

int main() {
    Derived D; D.unique_member_func(); D.common_member_func();

    Abstract* parent_ptr = &D;
    parent_ptr->unique_member_func();
    parent_ptr->common_member_func();

    Derived* child_ptr = &D;
    child_ptr->unique_member_func();
    child_ptr->common_member_func();
    return 0;
}

 

Operator Overloading

#include <iostream>
using namespace std;

class OperatorClass {
    float weight;
    float height;
    public:
        explicit OperatorClass(float w, float h) : weight{w}, height{h} {};
        ~OperatorClass(){};

        void operator()(){
            cout << weight << endl;
            cout << height << endl;
        };

        int operator+(OperatorClass& other){
            return weight + other.weight;
        };

        int operator-(OperatorClass& other){
            return weight - other.weight;
        };

        int operator*(OperatorClass& other){
            return weight * other.weight;
        };

        int operator/(OperatorClass& other){
            return weight / other.weight;
        };
};


int main() {
    OperatorClass obj{0.0, 1.0};
    obj();

    OperatorClass obj1{1.0, 2.0};
    OperatorClass obj2{2.0, 4.0};
    cout << obj1 + obj2 << endl;
    cout << obj1 - obj2 << endl;
    cout << obj1 * obj2 << endl;
    cout << obj1 / obj2 << endl;
    return 0;
}

 

 

 

Class and Object

Constant Class

#include <iostream>

int main() {
    const int a = 1;
    const float b = 3.14;
    const double c = 3.141592;
    const char d = 'A';
    
    return 0;
}
#include <iostream>
#include <string>
using namespace std;

class Date {
    public:
        int year;
        int month;
        int day;

        explicit Date(int c_year, int c_month, int c_day): year{c_year}, month{c_month}, day{c_day}{};

        string get_date() const {
            return to_string(year) + ':'  + to_string(month) + ':' + to_string(day);
        };
};

int main() {
    Date date1{2025, 1, 1};
    date1.get_date();
    date1.year; date1.month; date1.day;

    const Date date2{2025, 2, 1};
    date2.get_date();
    date2.year; date2.month; date2.day;

    return 0;
}
#include <iostream>
#include <string>
using namespace std;

class Date {
    public:
        int year;
        int month;
        int day;

        explicit Date(int c_year, int c_month, int c_day): year{c_year}, month{c_month}, day{c_day}{};

        string get_date()  {
            return to_string(year) + '-'  + to_string(month) + '-' + to_string(day);
        };

        string get_date() const {
            return to_string(year) + ':'  + to_string(month) + ':' + to_string(day);
        };
};

int main() {
    Date date1{2025, 1, 1};
    date1.get_date(); // '-'

    const Date date2{2025, 2, 1};
    date2.get_date(); // ':'

    return 0;
}

 

Functor

#include <iostream>
using namespace std;

class Functor {
    public:
        void operator()(){
        };
        int operator()(int param){
            return param;
        };
};


int main() {
    Functor func;
    func();
    func(1);

    return 0;
}

 

 

 

 


OS and System

  • <limits.h>: PATH_MAX
  • <fcntl.h>: O_CREAT, open()
  • <unistd.h>: getcwd(), read(), write(), close(), unlink(), rmdir()
  • <dirent.h>: dirent, opendir(), readdir(), closedir()
  • <sys/stat.h>: mkdir(), open(), ftruncate()
  • <cstuio>: rename(), remove()

 

 

CWD

  • <limits.h>: PATH_MAX
  • <unistd.h>: getcwd()
  • <dirent.h>: dirent, opendir(), readdir(), closedir()
#include <iostream>
#include <dirent.h> // DIR, dirent, opendir, readdir, closedir
#include <cstring>  // strcmp
#include <unistd.h> // getcwd
#include <limits.h> // PATH_MAX

using namespace std;

int main() {
    // CWD: Load
    char cwd[PATH_MAX];
    if (getcwd(cwd, sizeof(cwd)) != nullptr) {
        cout << cwd << endl;
    } else {
        cerr << "fail to load directory." << endl;
    }

    // CWD: Open, Read, Close
    DIR *dir;
    dir = opendir(cwd);
    if (dir == nullptr) {
        cerr << "fail to open directory." << endl;
        return 1;
    } else {
        struct dirent *entry;
        while ((entry = readdir(dir)) != nullptr) {
            cout << entry->d_name << endl;
        }
        closedir(dir);
    }

    return 0;
}

 

MKDIR, TOUCH 

  • <fcntl.h>: O_CREAT, open()
  • <sys/stat.h>: mkdir(), open(), ftruncate()
  • <unistd.h>: close()
#include <iostream>
#include <sys/stat.h> // mkdir, open, ftruncate
#include <fcntl.h>    // O_CREAT
#include <unistd.h>   // close

int main() {
    const char *dir_name = "new_dir";
    const char *file_name = "new_file.txt";

    // make directory
    if (mkdir(dir_name, 0755) == -1) {
        perror("fail to make a directory.");
        return 1;
    }

    // make file
    int fd = open(file_name, O_CREAT | O_WRONLY, 0644);
    if (fd == -1) {
        perror("fail to make a file.");
        return 1;
    } else {
        // file size
        if (ftruncate(fd, 0) == -1) {
            perror("fail to set size of the file.");
            close(fd);
            return 1;
        }
    }

    close(fd);
    return 0;
}

 

RMDIR

  • <unistd.h>: unlink(), rmdir()
#include <iostream>
#include <unistd.h> // unlink, rmdir

int main() {
    const char *file_name = "new_file.txt";
    const char *dir_name = "new_dir";

    // remove file
    if (unlink(file_name) == -1) {
        perror("fail to remove the file");
        return 1;
    }

    // remove directory
    if (rmdir(dir_name) == -1) {
        perror("fail to remove the directory.");
        return 1;
    }

    return 0;
}

 

RM

  • <cstdio>: std::remove
#include <iostream>
#include <cstdio> // std::remove

int main() {
    const char *file = "file_to_delete.txt";

    if (std::remove(file) == 0) {
        std::cout << "success to remove the file.: " << file << std::endl;
    } else {
        std::perror("fail to remove the file.");
    }

    return 0;
}

 

 

CP

  • <fcntl.h>: open()
  • <unistd.h>: read(), write(), close()
  • <cstring>: strerror()
  • <errno.h>: errono()
#include <iostream>
#include <fcntl.h>    // open
#include <unistd.h>   // read, write, close
#include <cstring>    // strerror
#include <errno.h>    // errno

int copy_file(const char *src, const char *dest) {
    int src_fd = open(src, O_RDONLY);
    if (src_fd == -1) {
        std::cerr << "fail to open source: " << strerror(errno) << std::endl;
        return 1;
    }

    int dest_fd = open(dest, O_WRONLY | O_CREAT | O_TRUNC, 0644);
    if (dest_fd == -1) {
        std::cerr << "fail to open copy-file: " << strerror(errno) << std::endl;
        close(src_fd);
        return 1;
    }

    char buffer[4096];
    ssize_t bytes_read;
    while ((bytes_read = read(src_fd, buffer, sizeof(buffer))) > 0) {
        if (write(dest_fd, buffer, bytes_read) != bytes_read) {
            std::cerr << "fail to copy from source: " << strerror(errno) << std::endl;
            close(src_fd);
            close(dest_fd);
            return 1;
        }
    }

    if (bytes_read == -1) {
        std::cerr << "fail to read source: " << strerror(errno) << std::endl;
    }

    close(src_fd);
    close(dest_fd);

    return 0;
}

int main() {
    const char *src_file = "source.txt";
    const char *dest_file = "destination.txt";

    if (copy_file(src_file, dest_file) != 0) {
        return 1;
    }
    std::cout << "success to copy the file." << std::endl;

    return 0;
}

 

MV

  • <cstdio>: rename()
#include <iostream>
#include <cstdio> // rename

int main() {
    const char *old_name = "old_file.txt";
    const char *new_name = "new_file.txt";

    if (rename(old_name, new_name) != 0) {
        perror("fail to rename file.");
        return 1;
    }

    std::cout << "success to move file." << std::endl;
    return 0;
}

 

 


C++ Standard Libaray

C++ Reference

  • <iostream>
  • <fstream>
  • <sstream>
  • <iomanip>
  • <string>
  • <cstring>
  • <cmath>
  • <ctime>

<iostream>

//

 

<fstream>

#include <iostream>
#include <fstream>

int main() {
    std::ofstream outFile("example.txt");

    if (!outFile) {
        std::cerr << "cannot file open." << std::endl;
        return 1;
    }
    else {
        outFile << "Hello, World!" << std::endl;
        outFile << "I am C++." << std::endl;
        outFile.close();
        return 0;
    };
}
#include <iostream>
#include <fstream>

int main() {
    std::ifstream inFile("example.txt");

    if (!inFile) {
        std::cerr << "cannot file open." << std::endl;
        return 1;
    }
    else {
        std::string line;
        while (std::getline(inFile, line)) {
            std::cout << line << std::endl;
        };
        inFile.close();
        return 0;
    };
}

 

<iomanip>

#include <iostream>
#include <iomanip>
#include <string>
// std::setw, std::setfill, std::left, std::right,
// std::setprecision, std::fixed, std::scientific, std::showpoint
// std::hex, std::dec, std::oct
// std::boolalpha, std::noboolalpha

int main() {
    std::string txt = "abc";
    std::cout << std::setw(10) << std::setfill('*') << txt << std::endl; // right align

    int weight = 60;
    std::cout << std::setw(10) << weight << std::endl; // right align
    std::cout << std::setw(10) << std::left << weight << std::endl;
    std::cout << std::setw(10) << std::right << weight << std::endl;

    double num = 312353.14159265358979;
    std::cout << std::fixed << std::setprecision(2) << num << std::endl;
    std::cout << std::fixed << std::setprecision(3) << num << std::endl;
    std::cout << std::scientific << std::setprecision(5) << num << std::endl;
    std::cout << std::setw(30) << std::setfill('*') << std::left << std::fixed << std::setprecision(5) << num << std::endl;

    bool flag = true;
    std::cout << std::boolalpha << flag << std::endl; // true, false
    std::cout << std::noboolalpha << flag << std::endl; // 1, 0


    return 0;
}

 

<sstream>

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

int main() {
    // istringstream
    istringstream iss1("a b c d e f"); char dummy_char;
    while (iss1 >> dummy_char) { cout << dummy_char << endl;};

    istringstream iss2("1 2 3 4 5 6"); int dummy_int;
    while (iss2 >> dummy_int) { cout << dummy_int << endl;};

    // ostringstream
    ostringstream oss;
    int a = 1; float b = 3.14; double c =3.141592;
    oss << a << b << c;
    cout << oss.str() << endl;

    // stringstream
    stringstream ss("apple banana cat dog\nearth\nfruit"); string dummy_string;
    while (ss >> dummy_string) { cout << dummy_string << endl;};

    stringstream ss_("apple|banana|cat|dog|earth|fruit"); string token; char delimeter('|');
    while (getline(ss_, token, delimeter)) { cout << token << endl;};

    return 0;
}

 

<string>

//

 

<cstdlib>

//

 

<cstring>

//

 

 

<cmath>

//

 

<ctime>

//

 

 

<filesystem>

//

 

 

 

 

 


Reference

'quantitative analysis > programming' 카테고리의 다른 글

CPP Build System and Library  (0) 2024.07.06
Intermediate CPP Programming  (0) 2024.07.06
Bash Programming  (0) 2024.02.26
Computational Environment Configuration  (0) 2023.08.14

+ Recent posts