Returning values
Type func(); Type& func(); const Type& func(); Type* func(); const Type* func(); const Type func(); Type&& func(); const Type&& func();
Taking parameters
Readble | Writable | Transfers ownership |
---|---|---|
Yes | Yes | Yes |
Yes | Yes | No |
Yes | No | No |
Yes | Yes | Depends |
Yes | No | Depends |
Yes | No | Yes |
Yes | Yes | Yes |
Yes | No | Yes |
void func(Type); void func(Type&); void func(const Type&); void func(Type&&); void func(Type*); void func(const Type*); void func(const Type); void func(const Type&&);
Reads | Modifies | Takes ownership |
---|---|---|
Yes | No | No |
Depends | Yes | No |
Yes | No | No |
Yes | Yes | Yes |
Depends | Depends | Depends |
Yes | No | Depends |
Yes | No | No |
Yes | No | Yes |
std::unique_ptr
std::shared_ptr std::weak_ptr
unique_ptr
shared_ptr
weak_ptr
shared_ptr
weak_ptr
std::unique_ptr
std::unique_ptr<T> std::unique_ptr<T>{new-allocated-pointer} std::unique_ptr<T, DeleterT>{pointer, deleter} std::make_unique<T>(initializer) std::make_unique<T[]>(array-size) std::make_unique_for_overwrite<T>() std::make_unique_for_overwrite<T[]>(array-size)
std::unique_ptr
auto createSequence(size_t length) {
auto seq = std::make_unique_for_overwrite<int[]>(length);
seq[0] = seq[1] = 1;
for (int i = 2; i < length; ++i) {
seq[i] = seq[i - 2] + seq[i - 1];
}
return seq;
};
auto fopenUnique(const char* filename, const char* flags) {
return std::unique_ptr<std::FILE, int(*)(std::FILE*)>{
std::fopen(filename, flags), &std::fclose};
}
int* ar = new int[10];
// adopt existing resource
auto unique_ar = std::unique_ptr<int[]>{ar};
// construct new resource
auto my_p = std::make_unique<int[]>(5);
// release ownership and aquire new resource
unique_ar = some_ptr;
// steal ownership
unique_ar = std::move(my_p);
std::shared_ptr
shared_ptr
use_count:
1
std::shared_ptr
shared_ptr
use_count:
1
weak_ptr
std::shared_ptr
shared_ptr
use_count:
1
weak_ptr
weak_ptr
std::shared_ptr
shared_ptr
use_count:
2
weak_ptr
weak_ptr
shared_ptr
std::shared_ptr
shared_ptr
use_count:
2
weak_ptr
shared_ptr
std::shared_ptr
shared_ptr
use_count:
1
weak_ptr
std::shared_ptr
weak_ptr
use_count:
0
std::shared_ptr
use_count
shared_ptr
shared_ptr
shared_ptr
std::shared_ptr
use_count
shared_ptr
shared_ptr
std::shared_ptr
use_count
shared_ptr(new Object{args})
use_count
make_shared<Object>(args)
std::shared_ptr
use_count
Resource* ptr = new Resource{};
std::shared_ptr smart1{ptr};
std::shared_ptr smart2{smart1};
std::shared_ptr smart3{ptr};
std::shared_ptr smart4{smart1};
use_count
smart1
smart2
smart3
smart4
std::shared_ptr
std::shared_ptr<T> std::shared_ptr{new-allocated-pointer} std::shared_ptr<T, DeleterT>{pointer, deleter} std::shared_ptr<T>{shared-ptr} std::shared_ptr<T>{weak-ptr} std::shared_ptr<T>{unique-ptr} std::shared_ptr<T>{shared-ptr, pointer} std::make_shared<T>(initializer) std::make_shared<T[]>(array-size) std::make_shared_for_overwrite<T>() std::make_shared_for_overwrite<T[]>(array-size) weak_ptr.lock() std::enable_shared_from_this shared_ptr.use_count()
aliasing constructor
std::shared_ptr
std::unique_ptr<int[]> createSequence(size_t length);
// steal from unique_ptr
std::shared_ptr<int[]> shared = createSequence(10);
auto shared1 = std::make_shared<std::string>("Hello");
auto shared2 = shared1; // copy ownership
std::weak_ptr weak = shared1; // only access
// (1)
auto reader1 = weak.lock(); // read through weak_ptr
if (!reader1) // weak_ptr could've been expired
std::cout << "expired";
else
somePointerUser(*reader1);
// (2)
std::shared_ptr reader2{weak}; // throws if expired
somePointerUser(*reader2);
assert(shared1.use_count() == 4);
struct point { int x, y; };
auto point_ptr = std::make_shared<point>(3, 5);
auto coord_ptr = std::shared_ptr<int>(point_ptr, &point_ptr->x);
std::weak_ptr
std::weak_ptr
std::weak_ptr
std::shared_pointer
std::weak_ptr
struct Person {
int age;
std::string name;
Job occupation;
};
class Array {
private:
int* data; // raw pointer encapsulated
size_t capacity;
public:
int& operator[](size_t idx);
const int& operator[](size_t idx) const;
...
};
public
inheritance
private
inheritance
protected
inheritance
public
inheritance
class Base {
};
class Derived : public Base {
};
Derived
Base
public
inheritance
class Base {
int x, y;
};
class Derived : public Base {
int z, w;
};
memory location
object
z
Base
w
x
y
public
inheritance
class Base {
int x, y;
};
class Derived : public Base {
int z, w;
};
memory location
object
z
Base
w
x
y
Empty Base Optimisation if
sizeof(Base) == 0
public
inheritance
class Base {
int x, y;
};
class Derived : public Base {
int z, w;
};
Derived derived;
Base* pBase = &derived;
Base& refBase = derived;
public
inheritance
class Base {
public:
void methodOnBase() {
std::cout << "base\n";
}
};
class Derived : public Base {
public:
void methodOnDerived() {
std::cout << "derived\n";
}
};
Base base;
base.methodOnBase();
Derived derived;
derived.methodOnDerived();
derived.methodOnBase();
public
inheritance
class Base {
public:
int data;
void methodOnBase() {
std::cout << data;
}
};
class Derived : public Base {
public:
void methodOnDerived() {
std::cout << data + 143;
}
};
Base base;
base.methodOnBase();
base.data = 245;
Derived derived;
derived.methodOnDerived();
derived.methodOnBase();
derived.data = 1252;
class Base {
public:
int data;
void methodOnBase() {
std::cout << data;
}
};
class Derived : public Base {
public:
void methodOnDerived() {
std::cout << data + 143;
}
};
Base base;
base.methodOnBase();
base.data = 245;
Derived derived;
derived.methodOnDerived();
derived.methodOnBase();
derived.data = 1252;
class Base {
int data;
public:
void methodOnBase() {
std::cout << data;
}
};
class Derived : public Base {
public:
void methodOnDerived() {
std::cout << data + 143;
}
};
Base base;
base.methodOnBase();
base.data = 245;
Derived derived;
derived.methodOnDerived();
derived.methodOnBase();
derived.data = 1252;
class Base {
protected:
int data;
public:
void methodOnBase() {
std::cout << data;
}
};
class Derived : public Base {
public:
void methodOnDerived() {
std::cout << data + 143;
}
};
Base base;
base.methodOnBase();
base.data = 245;
Derived derived;
derived.methodOnDerived();
derived.methodOnBase();
derived.data = 1252;
class Base {
protected:
int data;
public:
void methodOnBase() {
std::cout << data;
}
};
class Derived : public Base {
public:
void methodOnDerived() {
std::cout << data + 143;
}
};
Base base;
base.methodOnBase();
base.data = 245;
Derived derived;
derived.methodOnDerived();
derived.methodOnBase();
derived.data = 1252;
class Base {
protected:
int data;
public:
void methodOnBase() {
std::cout << data;
}
};
class Derived : public Base {
public:
using Base::data;
void methodOnDerived() {
std::cout << data + 143;
}
};
Base base;
base.methodOnBase();
base.data = 245;
Derived derived;
derived.methodOnDerived();
derived.methodOnBase();
derived.data = 1252;
class Base {
public:
void f() {
std::cout << "base";
};
};
class Derived : public Base {
};
Base base;
base.f(); // base
Derived derived;
derived.f(); // base
class Base {
public:
void f() {
std::cout << "base";
};
};
class Derived : public Base {
public:
void f() {
std::cout << "derived";
};
};
Base base;
base.f(); // base
Derived derived;
derived.f(); // derived
class Base {
public:
void f() {
std::cout << "base";
};
};
class Derived : public Base {
public:
void f(int x) {
std::cout << x;
};
};
Base base;
base.f(); // base
Derived derived;
derived.f(); // ERROR
derived.f(15); // 15
class Base {
public:
void f() {
std::cout << "base";
};
};
class Derived : public Base {
public:
using Base::f;
void f(int x) {
std::cout << x;
};
};
Base base;
base.f(); // base
Derived derived;
derived.f(); // ERROR
derived.f(15); // 15
shows relationship
code reuse
polymorphism
class Dog {
void bark();
};
class Terrier : public Dog {
void hunt();
};
class Dog {
virtual void bark();
};
class Terrier : public Dog {
void hunt() override;
};
type erasure, CRTP...
class Dog {
public:
void bark() {
std::cout << "I'm a generic dog\n";
}
};
class Terrier : public Dog {
public:
void bark() {
std::cout << "I'm a terrier\n";
};
};
std::unique_ptr<Dog> dog = std::make_unique<Terrier>();
dog->bark();
class Dog {
public:
virtual void bark() {
std::cout << "I'm a generic dog\n";
}
virtual ~Dog() = default;
};
class Terrier : public Dog {
public:
void bark() override {
std::cout << "I'm a terrier\n";
};
};
std::unique_ptr<Dog> dog = std::make_unique<Terrier>();
dog->bark();
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
protected members
using declaration
final specifier
private & protected inheritance
multiple inheritance
diamond problem
empty base optimization
base method hiding problem (shadowing)
virtual methods
override specifier
dynamic type
RTTI
dynamic_cast
typeid
vtables
by value passing problem (slicing)
pure virtual function
abstract class
misc
friends
nested members
conversion operators
operator overloading
member pointers
unions
std optional
std variant
std any
type ereasure
pimpl
enable shared from this with private inheritance
linkage and static (non-member) functions