# `std::shared_ptr<>` ___ ### `std::shared_ptr<>` * one object == multiple owners * last referrer destroys the object * copying allowed * moving allowed * can use custom deleter * can use custom allocator * has a control block == impact on size of pointer end efficiency shared pointers ___ ### `std::shared_ptr<>` usage (1) * Copying and moving is allowed
```cpp std::shared_ptr source(); void sink(std::shared_ptr ptr); void simpleUsage() { source(); sink(source()); auto ptr = source(); sink(ptr); sink(std::move(ptr)); auto p1 = source(); auto p2 = p1; p2 = std::move(p1); p1 = p2; p1 = std::move(p2); } ```
```cpp std::shared_ptr source(); void sink(std::shared_ptr ptr); void collections() { std::vector> v; v.push_back(source()); auto tmp = source(); v.push_back(tmp); v.push_back(std::move(tmp)); sink(v[0]); sink(std::move(v[0])); } ```
___ ### `std::shared_ptr<>` usage (2) ```cpp #include #include #include class Gadget {}; std::map> gadgets; void foo() { std::shared_ptr p1{new Gadget()}; // reference counter = 1 { auto p2 = p1; // copy (reference counter == 2) gadgets.insert(make_pair("mp3", p2)); // copy (reference counter == 3) p2->use(); } // destruction of p2, reference counter = 2 } // destruction of p1, reference counter = 1 int main() { foo(); gadgets.clear(); // reference counter = 0 - gadget is removed } ``` ___ ### Custom deleter * Don't change a type of shared_ptr because data is stored in control block * Don't change a size of shared_ptr because data is stored in control block * You can have a collection of shared_ptr which has different deleter
```C++ class Foo {}; void deleter1(Foo* const foo) { std::cout << "Deleter1\n"; delete foo; } int main() { std::vector> vec; std::shared_ptr ptr1(new Foo(), deleter1); vec.push_back(std::move(ptr1)); auto deleter2 = [](Foo* const foo) { std::cout << "Deleter2\n"; delete foo; }; vec.emplace_back(new Foo(), deleter2); } ```
```Bash Deleter1 Deleter2 ```
___ ### Problem with shared_ptr Let's look at a short story: * Programmer1 : Why do you pass shared_ptr by copy? Passing by copy increment counter (slower then unique or raw ptr) * Programmer2: Ok, so I will pass it by const reference instead! And avoid unnecessary incrementation of the control block. * Programmer1: So if you don't need to copy it (don't need to have 2 owners) why don't use unique_ptr? * Reassume: shared_ptr should be use only when given resource need to have few owners (very rare situation). In other case use always unique_ptr! ___ ### `std::shared_ptr<>` cyclic dependencies * What happens here?
```cpp #include struct Node { std::shared_ptr child; std::shared_ptr parent; }; int main () { auto root = std::shared_ptr(new Node); auto child = std::shared_ptr(new Node); root->child = child; child->parent = root; } ```
Memory leak! kot