RAII
mutable
class C {
    int member;
    void foo() const {
        member = 42;
    }
};mutable
class C {
    mutable int member;
    void foo() const {
        member = 42;
    }
};Constructors
class Stack {
private:
    std::vector<int> data;
public:
    static Stack createEmpty() {
        Stack s;
        return s;
    } 
    static Stack createFromVector(const std::vector<int>& numbers) {
        Stack s;
        s.data = numbers;
        return s;
    }
    static Stack createFromExisting(const Stack& st) {
        return createFromVector(st.data);
    }
    
    ...
};Stack s1 = Stack::createFromEmpty();
Stack s2 = Stack::createFromVector(v);
Stack s3 = Stack::createFromExisting(s2);Constructors
class Stack {
private:
    std::vector<int> data;
public:
    static Stack create() {
        Stack s;
        return s;
    } 
    static Stack create(const std::vector<int>& numbers) {
        Stack s;
        s.data = numbers;
        return s;
    }
    static Stack create(const Stack& st) {
        return createFromVector(st.data);
    }
    
    ...
};Stack s1 = Stack::create();
Stack s2 = Stack::create(v);
Stack s3 = Stack::create(s2);Constructors
class Stack {
private:
    std::vector<int> data;
public:
    Stack() 
    {
    } 
    Stack(const std::vector<int>& numbers) {
        data = numbers;
    }
    Stack(const Stack& st) {
        data = st.data;
    }
    
    ...
};Stack s1 = Stack();
Stack s2 = Stack(v);
Stack s3 = Stack(s2);Constructors
class Stack {
private:
    std::vector<int> data;
public:
    Stack() 
    {
    } 
    Stack(const std::vector<int>& numbers) {
        data = numbers;
    }
    Stack(const Stack& st) {
        data = st.data;
    }
    
    ...
};Stack s1;
Stack s2{v};
Stack s3{s2};Constructors
class Stack {
private:
    std::vector<int> data;
public:
    Stack() 
    {
    } 
    Stack(const std::vector<int>& numbers) {
        data = numbers;
    }
    Stack(const Stack& st) {
        data = st.data;
    }
    
    ...
};const Stack s1;
const Stack s2{v}; // error
const Stack s3{s2}; // errorConstructors
class Stack {
private:
    std::vector<int> data;
public:
    Stack() 
    {
    } 
    Stack(const std::vector<int>& numbers) :
        data{numbers}
    {
    }
    Stack(const Stack& st) : 
        data{st.data}
    {
    }
    
    ...
};const Stack s1;
const Stack s2{v};
const Stack s3{s2};Constructors
class ClassName {
    T1 member1;    
    T2 member2;
    T3 member3;
    ...
    TN memberN;
    ClassName(args) :
        member1{...},
        member2{...},
        member3{...},
        ...
        memberN{...}
    {
        ...
    }
};auto c1 = ClassName{args};
auto c2 = ClassName(args);
ClassName c3 = {args};
ClassName c4{args};
ClassName c5(args);new ClassName(args);
new ClassName{args};Constructor
class ClassName {
    T1 member1;    
    T2 member2;
    T3 member3;
    ...
    TN memberN;
    ClassName() :
        member1{...},
        member2{...},
        member3{...},
        ...
        memberN{...}
    {
        ...
    }
};ClassName c1;
auto c2 = ClassName{};
auto c3 = ClassName();
ClassName c4 = {};
ClassName c5{};
ClassName c6();new ClassName;
new ClassName();
new ClassName{};Default
class C {
    T1 member1;
    T1 member2;
    
    C(args) :
        member2{...}
        // member1
        // default-constructed
    {
    }
}Constructor
Default
struct Cls {
    std::vector<int> v;
    int coeff;
};struct Cls {
    std::vector<int> v;
    int coeff;
    
    Cls()
    {
    }
};struct Cls {
    std::vector<int> v;
    int coeff;
    
    Cls() :
        v{}
    {
    }
};Implicitly defined
Constructor
Default
struct Cls {
    std::vector<int> v;
    int coeff;
    
    Cls(args) {...}
};struct Cls {
    std::vector<int> v;
    int coeff;
    
    Cls(args) {...}
    
    Cls()
    {
    }
};struct Cls {
    std::vector<int> v;
    int coeff;
    
    Cls(args) {...}
    
    Cls() :
        v{}
    {
    }
};Implicitly defined
Constructor
Default
struct Cls {
    std::vector<int> v;
    int coeff;
    
    Cls(args) {...}
    
    Cls() = default;
};struct Cls {
    std::vector<int> v;
    int coeff;
    
    Cls(args) {...}
    
    Cls()
    {
    }
};struct Cls {
    std::vector<int> v;
    int coeff;
    
    Cls(args) {...}
    
    Cls() :
        v{}
    {
    }
};Explicitly defaulted
Constructor
Default
Explicitly deleted
struct Cls {
    std::vector<int> v;
    int coeff;
};struct Cls {
    std::vector<int> v;
    int coeff;
    
    Cls()
    {
    }
};struct Cls {
    std::vector<int> v;
    int coeff;
    
    Cls() :
        v{}
    {
    }
};Constructor
Default
Explicitly deleted
struct Cls {
    std::vector<int> v;
    int coeff;
    
    Cls() = delete;
};struct Cls {
    std::vector<int> v;
    int coeff;
    
    Cls()
    {
    }
};struct Cls {
    std::vector<int> v;
    int coeff;
    
    Cls() :
        v{}
    {
    }
};Constructor
Default
Trivial
struct Cls {
    std::vector<int> v;
    int coeff;
    
    Cls() = default;
};struct point2D {
    int x, y;
    
    point2D() = default;
};non trivial
trivial
Constructor
Default
struct Cls {
    std::vector<int> v;
    int coeff;
    
    Cls() = default;
};struct point2D {
    int x, y;
    
    point2D() = default;
};no-throw default constructible
trivially default constructible
struct Cls {
    std::vector<int> v;
    int coeff;
    
    Cls() noexcept
        = default;
};default constructible
#include <type_traits>
#include <type_traits>
#include <type_traits>
std::is_trivially_default_constructible_v<Cls>
std::is_nothrow_default_constructible_v<Cls>
std::is_default_constructible_v<Cls>
Constructor
struct Cls {
    std::vector<int> x;
    int y;
    
    // implicitly defined
};
Cls p1;
// p1.x == {}
// p1.y undefined
Cls p2{};
// p1.x == {}
// p1.y == 0Default
struct Cls {
    std::vector<int> x;
    int y;
    
    Cls()
    {
    }
};
Cls p1;
// p1.x == {}
// p1.y undefined
Cls p2{};
// p1.x == {}
// p1.y undefinedstruct Cls {
    std::vector<int> x;
    int y;
    
    Cls() : x{}, y{}
    {
    }
};
Cls p1;
// p1.x == {}
// p1.y == 0
Cls p2{};
// p1.x == {}
// p1.y == 0Defaulted
default constructor
User defined default constructor
User defined default constructor
struct Cls {
    std::vector<int> x;
    int y;
    
    Cls() = default;
};
Cls p1;
// p1.x == {}
// p1.y undefined
Cls p2{};
// p1.x == {}
// p1.y == 0point2D p1;
point2D p2{};
default initialization
value initialization
RAII and lifetime
- Storage allocation or reuse
 - Object construction
 - Â ... Object is alive ...
 - Object destruction
 - Storage deallocation or reuse
 
{
    std::string s;
    // storage allocated on stack
    // std::string constructor invoked
    //    internal string buffer allocated
    //    size set to 0
}
// storage deallocated on stack
// std::string destructor invoked
//    internal string buffer deallocatedRAII
Resource Acquisition Is Initialization
new
delete
fopen
fclose
libcreate
libdestroy
lock
unlock
RAII
Resource Acquisition Is Initialization
setup1();
setup2();
setup3();
...
work();
...
teardown3();
teardown2();
// forgot to teardown1()!setup();
...
work(); // exception thrown
...
teardown(); // not reachedsetup();
bool cleaned = false;
...
try {
    work();
catch(...) {
    cleaned = true;
    teardown();
}
...
if (!cleaned) {
    teardown();
}setup1();
setup2();
setup3();
...
work();
...
teardown3();
teardown2();
teardown1();setup1();
setup2();
setup3();
...
work();
...
// wrong order
teardown1();
teardown2();
teardown3();setup1();
setup2();
setup3();
...
work();
...
teardown3();
teardown2();
teardown1();RAII
Resource Acquisition Is Initialization
new
delete
fopen
fclose
libcreate
libdestroy
lock
unlock
Constructor
Destructor
destructors
class Resource {
    Resource(args) {
        // construct
    }
    ~Resource() {
        // destruct
    }
};{
    // Resource::Resource()
    Resource r;
    work(r);
} // Resource::~Resource()ClassName(args)
~ClassName()
Constructor
Destructor
class SmartArray {
private:
    int* _data;
    size_t _size;
public:
    SmartArray(size_t size) :
        _data{new int[size]},
        _size{size}
    {
    }
    ~SmartArray() {
        delete[] _data;
    }
    int& at(int i) {
        return _data[i];
    }
    const int& at(int i) const {
        return _data[i];
    }
    size_t size() {
        return _size;
    }
};{
    SmartArray ar{10};
    for (int i = 0; i < ar.size(); ++i) {
        ar.at(i) = i * i;
    }
} // SmartArray::~SmartArray()destructors
Constructors
class C {
public:
    C();
    C(int arg1 = 42);
};Default constructor
Copy constructor
Move constructor
Explicit constructor
class C {
public:
    C(const C&);
};class C {
public:
    C(C&&);
};class C {
public:
    explicit C(char);
};C c1;
// C c1(); most vexing parse
C c2{};
new C;
...C c3 = c1;
C c4{c1};
f(c1); // if by value
...C c4 = createTemporary();
C c5 = std::move(c2);C c1 = 'c'; // error
f('c'); // error (f takes C)
return 'c'; // error (returns C)
...Constructor
explicit
class SmartArray {
private:
    int* _data;
    size_t _size;
public:
    SmartArray(size_t size) :
        _data{new int[size]},
        _size{size}
    {
    }
    ~SmartArray() {
        delete[] _data;
    }
    int& at(int i) {
        return _data[i];
    }
    const int& at(int i) const {
        return _data[i];
    }
    size_t size() {
        return _size;
    }
};Explicit constructor
SmartArray f(const SmartArray& ar) {
    return 10;
}
void g() {
    SmartArray ar1 = static_cast<SmartArray>(10);
    SmartArray ar2 = 10;
    SmartArray ar3 = {10};
    f(10);
}converting constructor
Constructor
explicit
class SmartArray {
private:
    int* _data;
    size_t _size;
public:
    explicit SmartArray(size_t size) :
        _data{new int[size]},
        _size{size}
    {
    }
    ~SmartArray() {
        delete[] _data;
    }
    int& at(int i) {
        return _data[i];
    }
    const int& at(int i) const {
        return _data[i];
    }
    size_t size() {
        return _size;
    }
};Explicit constructor
SmartArray f(const SmartArray& ar) {
    return 10;
}
void g() {
    SmartArray ar1 = static_cast<SmartArray>(10);
    SmartArray ar2 = 10;
    SmartArray ar3 = {10};
    f(10);
}explicit constructor
SmartArray ar = {2, 3, 4, 5, 7};std::initializer_list
class SmartArray {
private:
    int* _data;
    size_t _size;
public:
    explicit SmartArray(size_t size) :
        _data{new int[size]},
        _size{size}
    {
    }
    ~SmartArray() {
        delete[] _data;
    }
    int& at(int i) {
        return _data[i];
    }
    const int& at(int i) const {
        return _data[i];
    }
    size_t size() {
        return _size;
    }
};class SmartArray {
private:
    int* _data;
    size_t _size;
public:
    explicit SmartArray(size_t size) :
        _data{new int[size]},
        _size{size}
    {
    }
    SmartArray(std::initializer_list<int> il) :
        _data{new int[il.size()]},
        _size{il.size()}
    {
        std::copy_n(il.begin(), il.size(), _data);
    }
    ~SmartArray() {
        delete[] _data;
    }
    int& at(int i) {
        return _data[i];
    }
    const int& at(int i) const {
        return _data[i];
    }
    size_t size() {
        return _size;
    }
};SmartArray ar = {2, 3, 4, 5, 7};std::initializer_list
struct point2D {
    int x, y;
    
    point2D() :
        x{13},
        y{42}
    {
    }
}in-class initializers
struct point2D {
    int x = 13, y = 42;
}=
struct point2D {
    int x, y = 42;
    
    point2D() :
        x{13}
    {
        // y == 42
    }
}in-class initializers
T obj;
T object {};
T()
T{}
new T()
new T{}
Class::Class(...) : member() { ... }
Class::Class(...) : member{} { ... }T object(args...);
T object{arg};
T(args);
static_cast<T>(obj)
new T(args...)
Class::Class() : member(args...) { ... }
[arg](){ ... }T object = other;
T object = {other};
f(other)
return other;
throw object;
catch (T object)
T array[N] = {other};T object{args...};
T{args...}
new T{args...}
class { T member{args...}; }
Class::Class() : member{args...} { ... }T object = {args...};
f({args...})
return {args...} ;
object[{args...}]
object = {args...}
U({args...})
Class { T member = {args...}; };T object = {args...};
T object{args...};
T object = { .designator = arg1 , .designator { arg2 } ... };
T object { .designator = arg1 , .designator { arg2 } ... };
T object(args...);T& ref = object;
T& ref = {args...};
T& ref(object);
T& ref{args...};
T&& ref = object;
T&& ref = {args...};
T&& ref(object) ;
T&& ref{args...};
f(object)
f({args...})
return object;
Class::Class(...) : ref(object) {...}Default
Value
Direct
Copy
Direct list
Copy list
Aggregate
Reference
initialization
To be continued...
RAII
RAII
inheritance
virtual
- constructor
 - member initializer list
 - destructor
 - default constructor
 - std::initializer_list
 - in-class initializer
 - copy ctor
 - cpy assign op
 - move ctor
 - mv assign op
 - default members
 - deleted members
 - rule of 0
 - rule of 3/5
 - smart-ptrs
 - converting constructor
 - explicit specifier
 
- is-a relation
 - has-a relation
 - public inheritance
 - final specifier
 - using declaration
 - empty base optimization
 - protected members
 - private & protected inheritance
 - multiple inheritance
 - diamond problem
 
- base method hiding problem
 - virtual methods
 - override specifier
 - dynamic type
	
- RTTI
 - dynamic_cast
 - typeid
 - vtables
 
 - by value passing problem
 - pure virtual function
 - abstract class
 
misc
- friends
 - nested members
 - conversion operators
 - operator overloading
 - member pointers
 - unions
	
- std optional
 - std variant
 - std any
 
 - user defined literal
 
RAII
By Jan Bielak
RAII
A presentation about constructors, destructors and RAII. It is presented here: https://www.youtube.com/watch?v=yDrIHAS2JgY .
- 806