SlideShare a Scribd company logo
1 of 32
Детально про найпростіші
“розумні” вказівники C++
||
The C++'s simplest smart pointers
in depth
Керування пам'яттю в C++
 Ручне керування пам'яттю
 Отримання ресурсу є ініціалізація ==
Resource acquisition is initialization == RAII
RAII
 Кожен ресурс обгортається в клас, в якому:
 конструктор отримує ресурс і встановлює всі
інваріанти класу, або кидає виключення, якщо це
не вдається зробити
 деструктор звільняє ресурс і не кидає виключень
 Ресурс завжди зберігається в об'єкті RAII-
класу, який створений на стеку чи
тимчасовий, або має час існування
обмежений іншим таким об'єктом
 Безпека виняткових ситуацій == ES
 Полегшує ранній вихід із функції чи циклу
Переваги RAII над збирачем
сміття (GC)
 Уніформне керування ресурсами:
оперативна пам'ять, потік (thread), відкритий
сокет, відкритий файл, заблокований
мʼютекс, з'єднання із БД
 Передбачуваний час існування об'єкта
 Сміття
 Ефективне використання пам'яті
 Відсутність неконтрольованих затримок для
видалення сміття
Переваги збирача сміття над RAII
 GC простіше використовувати в простих
ситуаціях
 GC дозволяє ефективно реалізувати деякі
постійні (persistent) структури даних
 RAII вимагає дисципліни розробника
 Код багатьох програм написаний на древньому
C++, частково на C
 Видалення двічі (UB)
 Розіменування “висячого” вказівника (UB)
 Протікання пам'яті
 Навіть коректний код складно
модифікувати/рефакторити
Приклад “Тимчасовий вказівник” 1
1 bool showDonut(int windowId)
2 {
3 Painter * const painter = makePainter(windowId);
4 return painter->showDonut();
5 }
Приклад “Тимчасовий вказівник” 2
1 bool showDonut(int windowId)
2 {
3 Painter * const painter = makePainter(windowId);
4 const bool result = painter->showDonut();
5 delete painter;
6 return result;
7 }
Приклад “Тимчасовий вказівник” 3
1 bool showDonut(int windowId)
2 {
3 Painter * const painter = makePainter(windowId);
4 if (!painter->hasKitchen())
5 return false;
6 const bool result = painter->showDonut();
7 delete painter;
8 return result;
9 }
Приклад “Тимчасовий вказівник” 4
1 bool showDonut(int windowId)
2 {
3 Painter * const painter = makePainter(windowId);
4 if (!painter->hasKitchen()) {
5 delete painter;
6 return false;
7 }
8 const bool result = painter->showDonut();
9 delete painter;
10 return result;
11 }
Приклад “Тимчасовий вказівник” 5
1 bool showDonut(int windowId)
2 {
3 Painter * const painter = makePainter(windowId);
4 try {
5 if (!painter->hasKitchen()) {
6 delete painter;
7 return false;
8 }
9 const bool result = painter->showDonut();
10 delete painter;
11 return result;
12 }
13 catch (...) {
14 delete painter;
15 throw;
16 }
17 }
Приклад “Тимчасовий вказівник” 6
1 bool showDonut(int windowId)
2 {
3 Painter * const painter = makePainter(windowId);
4 try {
5 Kitchen * const kitchen = painter->makeKitchen();
6 if (!kitchen) {
7 delete painter;
8 return false;
9 }
10 const bool result = kitchen->showDonut();
11 delete kitchen;
12 delete painter;
13 return result;
14 }
15 catch (...) {
16 delete painter;
17 throw;
18 }
19 }
Приклад “Тимчасовий вказівник” 7
1 bool showDonut(int windowId)
2 {
3 Painter * const painter = makePainter(windowId);
4 Kitchen * kitchen = nullptr;
5 try {
6 kitchen = painter->makeKitchen();
7 if (!kitchen) {
8 delete painter;
9 return false;
10 }
11 const bool result = kitchen->showDonut();
12 delete kitchen;
13 delete painter;
14 return result;
15 }
16 catch (...) {
17 delete kitchen;
18 delete painter;
19 throw;
20 }
21 }
Приклад “Тимчасовий вказівник” 2
1 bool showDonut(int windowId)
2 {
3 Painter * const painter = makePainter(windowId);
4 const bool result = painter->showDonut();
5 delete painter;
6 return result;
7 }
1 bool showDonut(int windowId)
2 {
3 using Ptr = const
std::unique_ptr<Painter>;
4 Ptr painter(makePainter(windowId));
5 return painter->showDonut();
6 }
Приклад “Тимчасовий вказівник” 4
1 bool showDonut(int windowId)
2 {
3 Painter * const painter = makePainter(windowId);
4 if (!painter->hasKitchen()) {
5 delete painter;
6 return false;
7 }
8 const bool result = painter->showDonut();
9 delete painter;
10 return result;
11 }
1 bool showDonut(int windowId)
2 {
3 using Ptr = const
std::unique_ptr<Painter>;
4 Ptr painter(makePainter(windowId));
5 if (!painter->hasKitchen())
6 return false;
7 return painter->showDonut();
8 }
Приклад “Тимчасовий вказівник” 5
1 bool showDonut(int windowId)
2 {
3 Painter * const painter = makePainter(windowId);
4 try {
5 if (!painter->hasKitchen()) {
6 delete painter;
7 return false;
8 }
9 const bool result = painter->showDonut();
10 delete painter;
11 return result;
12 }
13 catch (...) {
14 delete painter;
15 throw;
16 }
17 }
1 bool showDonut(int windowId)
2 {
3 using Ptr = const
std::unique_ptr<Painter>;
4 Ptr painter(makePainter(windowId));
5 if (!painter->hasKitchen())
6 return false;
7 return painter->showDonut();
8 }
Приклад “Тимчасовий вказівник” 7
1 bool showDonut(int windowId)
2 {
3 Painter * const painter = makePainter(windowId);
4 Kitchen * kitchen = nullptr;
5 try {
6 kitchen = painter->makeKitchen();
7 if (!kitchen) {
8 delete painter;
9 return false;
10 }
11 const bool result = kitchen->showDonut();
12 delete kitchen;
13 delete painter;
14 return result;
15 }
16 catch (...) {
17 delete kitchen;
18 delete painter;
19 throw;
20 }
21 }
1 bool showDonut(int windowId)
2 {
3 using Ptr = const
std::unique_ptr<Painter>;
4 Ptr painter(makePainter(windowId));
5 using Kptr = const
std::unique_ptr<Kitchen>;
6 Kptr kitchen(painter->makeKitchen());
7 if (!kitchen)
8 return false;
9 return kitchen->showDonut();
10 }
Приклад “Інтерфейс” 1
1 // Interface 1
2 Cookie * makeCookie(int size);
3 bool showCookie(Cookie * cookie);
4
5 // Interface 2
6 Cookie * getCookie(int size);
7 bool eatCookie(Cookie * cookie);
Приклад “Інтерфейс” 2
1 // Interface 1
2 Cookie * makeCookie(int size);
3 bool showCookie(Cookie & cookie);
4
5 // Interface 2
6 Cookie & getCookie(int size);
7 bool eatCookie(Cookie * cookie);
1 // Interface 1
2 Cookie * makeCookie(int size);
3 bool showCookie(Cookie * cookie);
4
5 // Interface 2
6 Cookie * getCookie(int size);
7 bool eatCookie(Cookie * cookie);
Приклад “Інтерфейс” 3
1 // Interface 1
2 Cookie * makeCookie(int size);
3 bool showCookie(Cookie * cookie);
4
5 // Interface 2
6 Cookie * getCookie(int size);
7 bool eatCookie(Cookie * cookie);
1 // Interface 1
2 std::unique_ptr<Cookie> makeCookie(int size);
3 bool showCookie(Cookie * cookie);
4
5 // Interface 2
6 Cookie * getCookie(int size);
7 bool eatCookie(std::unique_ptr<Cookie> && cookie);
Приклад “Інтерфейс” 4
1 // Interface 1
2 std::unique_ptr<Cookie> makeCookie(int size);
3 bool showCookie(std::observer_ptr<Cookie> cookie);
4 // std::observer_ptr may land in C++2x
5 // Interface 2
6 std::observer_ptr<Cookie> getCookie(int size);
7 bool eatCookie(std::unique_ptr<Cookie> && cookie);
1 // Interface 1
2 std::unique_ptr<Cookie> makeCookie(int size);
3 bool showCookie(Cookie * cookie);
4
5 // Interface 2
6 Cookie * getCookie(int size);
7 bool eatCookie(std::unique_ptr<Cookie> && cookie);
Приклад “Користувач” 3
2 std::unique_ptr<Cookie> makeCookie(int size);
7 bool eatCookie(std::unique_ptr<Cookie> && cookie);
1 auto cookie = makeCookie(47);
2 cookie->coverWithCream();
3 if (eatCookie(std::move(cookie)))
4 std::cout << "Yum!n";
Приклад “Користувач” 1
2 Cookie * makeCookie(int size);
7 bool eatCookie(Cookie * cookie);
1 auto * cookie = makeCookie(47);
2 try {
3 cookie->coverWithCream();
4 }
5 catch (...) {
6 delete cookie;
7 throw;
8 }
9 if (eatCookie(cookie)) {
10 std::cout << "Yum!n";
11 cookie = nullptr;
12 }
13 else
14 delete cookie;
Ефективність unique_ptr
 Реалізація unique_ptr використовує Empty
base optimization (EBO)
 Кожна операція над unique_ptr теоретично
повинна бути такою ж швидкою, як
відповідна операція над “голим” вказівником
 template <class T, class Deleter = std::default_delete<T>>
 class unique_ptr;
 sizeof(std::unique_ptr<T, Deleter>) == sizeof(T *)
 // (якщо Deleter — порожній клас)
unique_ptr чи стек?
 Варто оголошувати об'єкти на стеку у
функціях та за значенням у класах коли це
можливо: вбудовані типи, класи стандартної
бібліотеки, інші прості структури та класи. Це
простіше і ефективніше.
 Поліморфний об'єкт
 Вказівник на реалізацію (класу) ==
Pointer to implementation == Pimpl idiom ==
Opaque pointer
unique_ptr чи стек? (2)
 Потрібен стан відсутності - nullptr (краще
std::optional із C++17)
 Адреса об'єкта повинна бути сталою, але
власник об'єкта може змінюватись
 Переміщення об'єкту повільне або
неможливе
 Потрібне особливе видалення (custom
deleter)
Приклад “Особливе видалення”
1 // Interface
2 struct IppDeleter
3 {
4 void operator()(Ipp64f * p) const { ippsFree(p); }
5 };
6
7 using Ipp64fUniquePtr = std::unique_ptr<Ipp64f, IppDeleter>;
8
9 inline Ipp64fUniquePtr makeUniqueIpp64f(int len)
10 {
11 return Ipp64fUniquePtr(ippsMalloc_64f(len));
12 }
13
14 // Usage
15 auto factor = makeUniqueIpp64f(3);
Приклад make_unique (C++14)
1 // Interface
2 void combine(std::unique_ptr<A> && a, std::unique_pr<B> && b);
1 // Usage 1 (exception unsafe because of a possible interleaved order of
2 // execution of subexpressions in function parameters)
3 combine(std::unique_ptr<A>(new A(2)), std::unique_ptr<B>(new B));
4 combine(std::unique_ptr<A>(new A(2)), createB());
1 // Usage 2 (exception safe)
2 combine(std::make_unique<A>(2), std::make_unique<B>());
3 combine(std::make_unique<A>(2), createB());
Приклад make_unique 2 (C++14)
1 // Declaration
2 std::vector<std::unique_ptr<Biscuit>> biscuits;
1 // Usage 1 (line 2 is long; line 3 is exception unsafe: if emplace_back throws)
2 biscuits.push_back(std::unique_ptr<Biscuit>(new Biscuit));
3 biscuits.emplace_back(new Biscuit);
1 // Usage 2 (exception safe)
2 biscuits.push_back(std::make_unique<Biscuit>());
3 biscuits.emplace_back(std::make_unique<Biscuit>());
1 // "Naked" declaration
2 std::vector<Biscuit *> biscuits;
1 // "Naked" usage 1 (exception unsafe)
2 biscuits.push_back(new Biscuit);
1 // "Naked" usage 2 (exception safe)
2 biscuits.push_back(nullptr);
3 biscuits.back() = new Biscuit;
 Як щодо
асоціативних
контейнерів?
(std::set, std::map,
std::unordered_set
, std::multimap, ...)
std::auto_ptr
 Доступний в C++98
 Не інтуїтивна семантика копіювання
 Не може бути використаний в контейнерах
 Deprecated in C++11
 Removed in C++17
 Може бути легко замінений на unique_ptr
Приклад “Вказівник на реалізацію”
1 // Spacer.h
2 class Spacer
3 {
4 public:
5 Spacer();
6 ~Spacer();
7 // ...
8 private:
9 class Impl;
10 std::unique_ptr<Impl> impl_;
11 };
12
13 // Spacer.cpp
14 class Spacer::Impl
15 {
16 // ...
17 };
18 Spacer::Spacer() : impl_(std::make_unique<Impl>()) {}
19 // Destructor definition must be in the cpp file because the
20 // implicitly invoked Impl's destructor needs complete type
21 Spacer::~Spacer() = default;
Спеціалізація для масивів
 Зазвичай std::vector або std::string зручніші.
 Функція, яку не можна змінити (бібліотечна
функція), приймає/вертає вказівник на масив
 unique_ptr<T[]> ефективніший в деяких
ситуаціях:
 new T[n] виділяє пам'ять для рівно n елементів
 new T[n] не ініціює елементи, якщо T - POD
 template <class T, class Deleter> class unique_ptr<T[], Deleter>;
Ваші запитання

More Related Content

What's hot

"Unit testing in AngularJS" Виктор Зозуляк
"Unit testing in AngularJS" Виктор Зозуляк"Unit testing in AngularJS" Виктор Зозуляк
"Unit testing in AngularJS" Виктор ЗозулякFwdays
 
System programing module 2. Threads
System programing module 2. ThreadsSystem programing module 2. Threads
System programing module 2. ThreadsAndrii Hladkyi
 
Asynchronous programming in .NET (UA)
Asynchronous programming in .NET (UA)Asynchronous programming in .NET (UA)
Asynchronous programming in .NET (UA)Oleksandr Pavlyshak
 
06 Pointers To Class Members
06 Pointers To Class Members06 Pointers To Class Members
06 Pointers To Class Membersolegapster
 
NET Framework and C# Module 12.2. Garbage Collector
NET Framework and C# Module 12.2. Garbage CollectorNET Framework and C# Module 12.2. Garbage Collector
NET Framework and C# Module 12.2. Garbage CollectorAndrii Hladkyi
 
Prometheus. Масовий онлайн курс "Основи програмування". Лекція 5
Prometheus. Масовий онлайн курс "Основи програмування". Лекція 5Prometheus. Масовий онлайн курс "Основи програмування". Лекція 5
Prometheus. Масовий онлайн курс "Основи програмування". Лекція 5Nikita Pavliuchenko
 

What's hot (12)

"Unit testing in AngularJS" Виктор Зозуляк
"Unit testing in AngularJS" Виктор Зозуляк"Unit testing in AngularJS" Виктор Зозуляк
"Unit testing in AngularJS" Виктор Зозуляк
 
System programing module 2. Threads
System programing module 2. ThreadsSystem programing module 2. Threads
System programing module 2. Threads
 
Asynchronous programming in .NET (UA)
Asynchronous programming in .NET (UA)Asynchronous programming in .NET (UA)
Asynchronous programming in .NET (UA)
 
cpp-2013 #20 Best practices
cpp-2013 #20 Best practicescpp-2013 #20 Best practices
cpp-2013 #20 Best practices
 
04 Operators
04 Operators04 Operators
04 Operators
 
Tdd, ти де?
Tdd, ти де?Tdd, ти де?
Tdd, ти де?
 
cpp-2013 #19 Concurrency
cpp-2013 #19 Concurrencycpp-2013 #19 Concurrency
cpp-2013 #19 Concurrency
 
06 Pointers To Class Members
06 Pointers To Class Members06 Pointers To Class Members
06 Pointers To Class Members
 
Theme23-oop2
Theme23-oop2Theme23-oop2
Theme23-oop2
 
General Functors ...
General Functors                                                             ...General Functors                                                             ...
General Functors ...
 
NET Framework and C# Module 12.2. Garbage Collector
NET Framework and C# Module 12.2. Garbage CollectorNET Framework and C# Module 12.2. Garbage Collector
NET Framework and C# Module 12.2. Garbage Collector
 
Prometheus. Масовий онлайн курс "Основи програмування". Лекція 5
Prometheus. Масовий онлайн курс "Основи програмування". Лекція 5Prometheus. Масовий онлайн курс "Основи програмування". Лекція 5
Prometheus. Масовий онлайн курс "Основи програмування". Лекція 5
 

Viewers also liked

2016.05.23 SSCGTHV INFORMA - NOUS LLOCS DE TREBALL
2016.05.23 SSCGTHV INFORMA - NOUS LLOCS DE TREBALL 2016.05.23 SSCGTHV INFORMA - NOUS LLOCS DE TREBALL
2016.05.23 SSCGTHV INFORMA - NOUS LLOCS DE TREBALL SSCGTHV VILADECANS
 
2015.10.27 SSCGTHV - INFORMATIVO PIDE LOS DIAS YA
2015.10.27 SSCGTHV - INFORMATIVO PIDE LOS DIAS YA2015.10.27 SSCGTHV - INFORMATIVO PIDE LOS DIAS YA
2015.10.27 SSCGTHV - INFORMATIVO PIDE LOS DIAS YASSCGTHV VILADECANS
 
AS GLBSGVOC Exhibitor App. 2016 Autism Acceptance Walk and Resource Fair
AS GLBSGVOC Exhibitor App.  2016 Autism Acceptance Walk and Resource FairAS GLBSGVOC Exhibitor App.  2016 Autism Acceptance Walk and Resource Fair
AS GLBSGVOC Exhibitor App. 2016 Autism Acceptance Walk and Resource FairRegina Moreno
 
Ecoscope Level 2 cert.
Ecoscope Level 2 cert.Ecoscope Level 2 cert.
Ecoscope Level 2 cert.Ekkadit S.
 
A Novel Methodology for the Separation of Known Suspended Microplastics (&lt;...
A Novel Methodology for the Separation of Known Suspended Microplastics (&lt;...A Novel Methodology for the Separation of Known Suspended Microplastics (&lt;...
A Novel Methodology for the Separation of Known Suspended Microplastics (&lt;...MACE Lab
 
La+propiedad+y+la+comunidad
La+propiedad+y+la+comunidadLa+propiedad+y+la+comunidad
La+propiedad+y+la+comunidadheibercolmenarez
 
Espacio geográfico y división político-territorial
Espacio geográfico y división político-territorial  Espacio geográfico y división político-territorial
Espacio geográfico y división político-territorial elianah14
 

Viewers also liked (11)

2016.05.23 SSCGTHV INFORMA - NOUS LLOCS DE TREBALL
2016.05.23 SSCGTHV INFORMA - NOUS LLOCS DE TREBALL 2016.05.23 SSCGTHV INFORMA - NOUS LLOCS DE TREBALL
2016.05.23 SSCGTHV INFORMA - NOUS LLOCS DE TREBALL
 
Continuity
ContinuityContinuity
Continuity
 
2015.10.27 SSCGTHV - INFORMATIVO PIDE LOS DIAS YA
2015.10.27 SSCGTHV - INFORMATIVO PIDE LOS DIAS YA2015.10.27 SSCGTHV - INFORMATIVO PIDE LOS DIAS YA
2015.10.27 SSCGTHV - INFORMATIVO PIDE LOS DIAS YA
 
Curso ehrpp
Curso ehrppCurso ehrpp
Curso ehrpp
 
AS GLBSGVOC Exhibitor App. 2016 Autism Acceptance Walk and Resource Fair
AS GLBSGVOC Exhibitor App.  2016 Autism Acceptance Walk and Resource FairAS GLBSGVOC Exhibitor App.  2016 Autism Acceptance Walk and Resource Fair
AS GLBSGVOC Exhibitor App. 2016 Autism Acceptance Walk and Resource Fair
 
Ecoscope Level 2 cert.
Ecoscope Level 2 cert.Ecoscope Level 2 cert.
Ecoscope Level 2 cert.
 
A Novel Methodology for the Separation of Known Suspended Microplastics (&lt;...
A Novel Methodology for the Separation of Known Suspended Microplastics (&lt;...A Novel Methodology for the Separation of Known Suspended Microplastics (&lt;...
A Novel Methodology for the Separation of Known Suspended Microplastics (&lt;...
 
La+propiedad+y+la+comunidad
La+propiedad+y+la+comunidadLa+propiedad+y+la+comunidad
La+propiedad+y+la+comunidad
 
Cuadro+informativo
Cuadro+informativoCuadro+informativo
Cuadro+informativo
 
Perda 14 th 2012 bumd
Perda 14 th 2012   bumdPerda 14 th 2012   bumd
Perda 14 th 2012 bumd
 
Espacio geográfico y división político-territorial
Espacio geográfico y división político-territorial  Espacio geográfico y división político-territorial
Espacio geográfico y división político-territorial
 

Similar to IT Talks The c++'s simplest smart pointers in depth

02 Copying Objects
02 Copying Objects02 Copying Objects
02 Copying Objectsolegapster
 
"Is there life in react without redux" by Babich Sergiy. OdessaJS'2021
"Is there life in react without redux" by Babich Sergiy. OdessaJS'2021"Is there life in react without redux" by Babich Sergiy. OdessaJS'2021
"Is there life in react without redux" by Babich Sergiy. OdessaJS'2021OdessaJS Conf
 
Net framework і c# module 15
Net framework і c# module 15Net framework і c# module 15
Net framework і c# module 15Andrii Hladkyi
 
Основи мови Ci
Основи мови CiОснови мови Ci
Основи мови CiEscuela
 
"How I don't need a state management library in React app", Tetiana Melnyk
"How I don't need a state management library in React app", Tetiana Melnyk "How I don't need a state management library in React app", Tetiana Melnyk
"How I don't need a state management library in React app", Tetiana Melnyk Fwdays
 
Mka python jr-urok_03_ua_1563258828
Mka python jr-urok_03_ua_1563258828Mka python jr-urok_03_ua_1563258828
Mka python jr-urok_03_ua_1563258828PavloTsiura
 
General Functors
General FunctorsGeneral Functors
General FunctorsDzendzula
 
Play Mongodb
Play MongodbPlay Mongodb
Play MongodbInfinity
 
JS Fest 2019/Autumn. Роман Савіцький. Webcomponents & lit-element in production
JS Fest 2019/Autumn. Роман Савіцький. Webcomponents & lit-element in productionJS Fest 2019/Autumn. Роман Савіцький. Webcomponents & lit-element in production
JS Fest 2019/Autumn. Роман Савіцький. Webcomponents & lit-element in productionJSFestUA
 
Роман Савіцький, "Webcomponents & lit-element in production."
Роман Савіцький, "Webcomponents & lit-element in production."Роман Савіцький, "Webcomponents & lit-element in production."
Роман Савіцький, "Webcomponents & lit-element in production."Sigma Software
 
iPhone Objective-C Development (ukr) (2009)
iPhone Objective-C Development (ukr) (2009)iPhone Objective-C Development (ukr) (2009)
iPhone Objective-C Development (ukr) (2009)Anatoliy Okhotnikov
 
07 - vysnovky z tdd, pohliad pochatkivtsia - vitalii zinchenko it event 2013...
07 -  vysnovky z tdd, pohliad pochatkivtsia - vitalii zinchenko it event 2013...07 -  vysnovky z tdd, pohliad pochatkivtsia - vitalii zinchenko it event 2013...
07 - vysnovky z tdd, pohliad pochatkivtsia - vitalii zinchenko it event 2013...Igor Bronovskyy
 

Similar to IT Talks The c++'s simplest smart pointers in depth (17)

передача параметрів в функції
передача параметрів в функціїпередача параметрів в функції
передача параметрів в функції
 
Design patterns part 1
Design patterns part 1Design patterns part 1
Design patterns part 1
 
02 Copying Objects
02 Copying Objects02 Copying Objects
02 Copying Objects
 
"Is there life in react without redux" by Babich Sergiy. OdessaJS'2021
"Is there life in react without redux" by Babich Sergiy. OdessaJS'2021"Is there life in react without redux" by Babich Sergiy. OdessaJS'2021
"Is there life in react without redux" by Babich Sergiy. OdessaJS'2021
 
Net framework і c# module 15
Net framework і c# module 15Net framework і c# module 15
Net framework і c# module 15
 
Модулі Python
Модулі PythonМодулі Python
Модулі Python
 
Funkciji1
Funkciji1Funkciji1
Funkciji1
 
Основи мови Ci
Основи мови CiОснови мови Ci
Основи мови Ci
 
"How I don't need a state management library in React app", Tetiana Melnyk
"How I don't need a state management library in React app", Tetiana Melnyk "How I don't need a state management library in React app", Tetiana Melnyk
"How I don't need a state management library in React app", Tetiana Melnyk
 
Mka python jr-urok_03_ua_1563258828
Mka python jr-urok_03_ua_1563258828Mka python jr-urok_03_ua_1563258828
Mka python jr-urok_03_ua_1563258828
 
General Functors
General FunctorsGeneral Functors
General Functors
 
Design patterns part 2
Design patterns part 2Design patterns part 2
Design patterns part 2
 
Play Mongodb
Play MongodbPlay Mongodb
Play Mongodb
 
JS Fest 2019/Autumn. Роман Савіцький. Webcomponents & lit-element in production
JS Fest 2019/Autumn. Роман Савіцький. Webcomponents & lit-element in productionJS Fest 2019/Autumn. Роман Савіцький. Webcomponents & lit-element in production
JS Fest 2019/Autumn. Роман Савіцький. Webcomponents & lit-element in production
 
Роман Савіцький, "Webcomponents & lit-element in production."
Роман Савіцький, "Webcomponents & lit-element in production."Роман Савіцький, "Webcomponents & lit-element in production."
Роман Савіцький, "Webcomponents & lit-element in production."
 
iPhone Objective-C Development (ukr) (2009)
iPhone Objective-C Development (ukr) (2009)iPhone Objective-C Development (ukr) (2009)
iPhone Objective-C Development (ukr) (2009)
 
07 - vysnovky z tdd, pohliad pochatkivtsia - vitalii zinchenko it event 2013...
07 -  vysnovky z tdd, pohliad pochatkivtsia - vitalii zinchenko it event 2013...07 -  vysnovky z tdd, pohliad pochatkivtsia - vitalii zinchenko it event 2013...
07 - vysnovky z tdd, pohliad pochatkivtsia - vitalii zinchenko it event 2013...
 

More from Vadym Muliavka

Mykhailo Zarai "Be careful when dealing with C++" at Rivne IT Talks
Mykhailo Zarai "Be careful when dealing with C++" at Rivne IT TalksMykhailo Zarai "Be careful when dealing with C++" at Rivne IT Talks
Mykhailo Zarai "Be careful when dealing with C++" at Rivne IT TalksVadym Muliavka
 
Roman Valchuk "Introducing to DevOps technologies"
Roman Valchuk "Introducing to DevOps technologies"Roman Valchuk "Introducing to DevOps technologies"
Roman Valchuk "Introducing to DevOps technologies"Vadym Muliavka
 
IT Talks "VR Tips for Engineers and Developers"
IT Talks "VR Tips for Engineers and Developers"IT Talks "VR Tips for Engineers and Developers"
IT Talks "VR Tips for Engineers and Developers"Vadym Muliavka
 
Rivne IT Talks How to programa Quantum Computer?
Rivne IT Talks How to programa Quantum Computer?Rivne IT Talks How to programa Quantum Computer?
Rivne IT Talks How to programa Quantum Computer?Vadym Muliavka
 
IT Talks The approach for solving impossible tasks (dynamic programming)
IT Talks The approach for solving impossible tasks (dynamic programming)IT Talks The approach for solving impossible tasks (dynamic programming)
IT Talks The approach for solving impossible tasks (dynamic programming)Vadym Muliavka
 
Bug reporting and tracking
Bug reporting and trackingBug reporting and tracking
Bug reporting and trackingVadym Muliavka
 
Boundary value analysis
Boundary value analysisBoundary value analysis
Boundary value analysisVadym Muliavka
 
Equivalence partitions analysis
Equivalence partitions analysisEquivalence partitions analysis
Equivalence partitions analysisVadym Muliavka
 
IT Talks Автоматизація тестування з допомогою Selenium
IT Talks Автоматизація тестування з допомогою SeleniumIT Talks Автоматизація тестування з допомогою Selenium
IT Talks Автоматизація тестування з допомогою SeleniumVadym Muliavka
 
IT Talks Тестування та аналіз вимог
IT Talks Тестування та аналіз вимогIT Talks Тестування та аналіз вимог
IT Talks Тестування та аналіз вимогVadym Muliavka
 
IT Talks QA - якість процесів розробки
IT Talks QA - якість процесів розробкиIT Talks QA - якість процесів розробки
IT Talks QA - якість процесів розробкиVadym Muliavka
 

More from Vadym Muliavka (11)

Mykhailo Zarai "Be careful when dealing with C++" at Rivne IT Talks
Mykhailo Zarai "Be careful when dealing with C++" at Rivne IT TalksMykhailo Zarai "Be careful when dealing with C++" at Rivne IT Talks
Mykhailo Zarai "Be careful when dealing with C++" at Rivne IT Talks
 
Roman Valchuk "Introducing to DevOps technologies"
Roman Valchuk "Introducing to DevOps technologies"Roman Valchuk "Introducing to DevOps technologies"
Roman Valchuk "Introducing to DevOps technologies"
 
IT Talks "VR Tips for Engineers and Developers"
IT Talks "VR Tips for Engineers and Developers"IT Talks "VR Tips for Engineers and Developers"
IT Talks "VR Tips for Engineers and Developers"
 
Rivne IT Talks How to programa Quantum Computer?
Rivne IT Talks How to programa Quantum Computer?Rivne IT Talks How to programa Quantum Computer?
Rivne IT Talks How to programa Quantum Computer?
 
IT Talks The approach for solving impossible tasks (dynamic programming)
IT Talks The approach for solving impossible tasks (dynamic programming)IT Talks The approach for solving impossible tasks (dynamic programming)
IT Talks The approach for solving impossible tasks (dynamic programming)
 
Bug reporting and tracking
Bug reporting and trackingBug reporting and tracking
Bug reporting and tracking
 
Boundary value analysis
Boundary value analysisBoundary value analysis
Boundary value analysis
 
Equivalence partitions analysis
Equivalence partitions analysisEquivalence partitions analysis
Equivalence partitions analysis
 
IT Talks Автоматизація тестування з допомогою Selenium
IT Talks Автоматизація тестування з допомогою SeleniumIT Talks Автоматизація тестування з допомогою Selenium
IT Talks Автоматизація тестування з допомогою Selenium
 
IT Talks Тестування та аналіз вимог
IT Talks Тестування та аналіз вимогIT Talks Тестування та аналіз вимог
IT Talks Тестування та аналіз вимог
 
IT Talks QA - якість процесів розробки
IT Talks QA - якість процесів розробкиIT Talks QA - якість процесів розробки
IT Talks QA - якість процесів розробки
 

IT Talks The c++'s simplest smart pointers in depth

  • 1. Детально про найпростіші “розумні” вказівники C++ || The C++'s simplest smart pointers in depth
  • 2. Керування пам'яттю в C++  Ручне керування пам'яттю  Отримання ресурсу є ініціалізація == Resource acquisition is initialization == RAII
  • 3. RAII  Кожен ресурс обгортається в клас, в якому:  конструктор отримує ресурс і встановлює всі інваріанти класу, або кидає виключення, якщо це не вдається зробити  деструктор звільняє ресурс і не кидає виключень  Ресурс завжди зберігається в об'єкті RAII- класу, який створений на стеку чи тимчасовий, або має час існування обмежений іншим таким об'єктом  Безпека виняткових ситуацій == ES  Полегшує ранній вихід із функції чи циклу
  • 4. Переваги RAII над збирачем сміття (GC)  Уніформне керування ресурсами: оперативна пам'ять, потік (thread), відкритий сокет, відкритий файл, заблокований мʼютекс, з'єднання із БД  Передбачуваний час існування об'єкта  Сміття  Ефективне використання пам'яті  Відсутність неконтрольованих затримок для видалення сміття
  • 5. Переваги збирача сміття над RAII  GC простіше використовувати в простих ситуаціях  GC дозволяє ефективно реалізувати деякі постійні (persistent) структури даних  RAII вимагає дисципліни розробника  Код багатьох програм написаний на древньому C++, частково на C  Видалення двічі (UB)  Розіменування “висячого” вказівника (UB)  Протікання пам'яті  Навіть коректний код складно модифікувати/рефакторити
  • 6. Приклад “Тимчасовий вказівник” 1 1 bool showDonut(int windowId) 2 { 3 Painter * const painter = makePainter(windowId); 4 return painter->showDonut(); 5 }
  • 7. Приклад “Тимчасовий вказівник” 2 1 bool showDonut(int windowId) 2 { 3 Painter * const painter = makePainter(windowId); 4 const bool result = painter->showDonut(); 5 delete painter; 6 return result; 7 }
  • 8. Приклад “Тимчасовий вказівник” 3 1 bool showDonut(int windowId) 2 { 3 Painter * const painter = makePainter(windowId); 4 if (!painter->hasKitchen()) 5 return false; 6 const bool result = painter->showDonut(); 7 delete painter; 8 return result; 9 }
  • 9. Приклад “Тимчасовий вказівник” 4 1 bool showDonut(int windowId) 2 { 3 Painter * const painter = makePainter(windowId); 4 if (!painter->hasKitchen()) { 5 delete painter; 6 return false; 7 } 8 const bool result = painter->showDonut(); 9 delete painter; 10 return result; 11 }
  • 10. Приклад “Тимчасовий вказівник” 5 1 bool showDonut(int windowId) 2 { 3 Painter * const painter = makePainter(windowId); 4 try { 5 if (!painter->hasKitchen()) { 6 delete painter; 7 return false; 8 } 9 const bool result = painter->showDonut(); 10 delete painter; 11 return result; 12 } 13 catch (...) { 14 delete painter; 15 throw; 16 } 17 }
  • 11. Приклад “Тимчасовий вказівник” 6 1 bool showDonut(int windowId) 2 { 3 Painter * const painter = makePainter(windowId); 4 try { 5 Kitchen * const kitchen = painter->makeKitchen(); 6 if (!kitchen) { 7 delete painter; 8 return false; 9 } 10 const bool result = kitchen->showDonut(); 11 delete kitchen; 12 delete painter; 13 return result; 14 } 15 catch (...) { 16 delete painter; 17 throw; 18 } 19 }
  • 12. Приклад “Тимчасовий вказівник” 7 1 bool showDonut(int windowId) 2 { 3 Painter * const painter = makePainter(windowId); 4 Kitchen * kitchen = nullptr; 5 try { 6 kitchen = painter->makeKitchen(); 7 if (!kitchen) { 8 delete painter; 9 return false; 10 } 11 const bool result = kitchen->showDonut(); 12 delete kitchen; 13 delete painter; 14 return result; 15 } 16 catch (...) { 17 delete kitchen; 18 delete painter; 19 throw; 20 } 21 }
  • 13. Приклад “Тимчасовий вказівник” 2 1 bool showDonut(int windowId) 2 { 3 Painter * const painter = makePainter(windowId); 4 const bool result = painter->showDonut(); 5 delete painter; 6 return result; 7 } 1 bool showDonut(int windowId) 2 { 3 using Ptr = const std::unique_ptr<Painter>; 4 Ptr painter(makePainter(windowId)); 5 return painter->showDonut(); 6 }
  • 14. Приклад “Тимчасовий вказівник” 4 1 bool showDonut(int windowId) 2 { 3 Painter * const painter = makePainter(windowId); 4 if (!painter->hasKitchen()) { 5 delete painter; 6 return false; 7 } 8 const bool result = painter->showDonut(); 9 delete painter; 10 return result; 11 } 1 bool showDonut(int windowId) 2 { 3 using Ptr = const std::unique_ptr<Painter>; 4 Ptr painter(makePainter(windowId)); 5 if (!painter->hasKitchen()) 6 return false; 7 return painter->showDonut(); 8 }
  • 15. Приклад “Тимчасовий вказівник” 5 1 bool showDonut(int windowId) 2 { 3 Painter * const painter = makePainter(windowId); 4 try { 5 if (!painter->hasKitchen()) { 6 delete painter; 7 return false; 8 } 9 const bool result = painter->showDonut(); 10 delete painter; 11 return result; 12 } 13 catch (...) { 14 delete painter; 15 throw; 16 } 17 } 1 bool showDonut(int windowId) 2 { 3 using Ptr = const std::unique_ptr<Painter>; 4 Ptr painter(makePainter(windowId)); 5 if (!painter->hasKitchen()) 6 return false; 7 return painter->showDonut(); 8 }
  • 16. Приклад “Тимчасовий вказівник” 7 1 bool showDonut(int windowId) 2 { 3 Painter * const painter = makePainter(windowId); 4 Kitchen * kitchen = nullptr; 5 try { 6 kitchen = painter->makeKitchen(); 7 if (!kitchen) { 8 delete painter; 9 return false; 10 } 11 const bool result = kitchen->showDonut(); 12 delete kitchen; 13 delete painter; 14 return result; 15 } 16 catch (...) { 17 delete kitchen; 18 delete painter; 19 throw; 20 } 21 } 1 bool showDonut(int windowId) 2 { 3 using Ptr = const std::unique_ptr<Painter>; 4 Ptr painter(makePainter(windowId)); 5 using Kptr = const std::unique_ptr<Kitchen>; 6 Kptr kitchen(painter->makeKitchen()); 7 if (!kitchen) 8 return false; 9 return kitchen->showDonut(); 10 }
  • 17. Приклад “Інтерфейс” 1 1 // Interface 1 2 Cookie * makeCookie(int size); 3 bool showCookie(Cookie * cookie); 4 5 // Interface 2 6 Cookie * getCookie(int size); 7 bool eatCookie(Cookie * cookie);
  • 18. Приклад “Інтерфейс” 2 1 // Interface 1 2 Cookie * makeCookie(int size); 3 bool showCookie(Cookie & cookie); 4 5 // Interface 2 6 Cookie & getCookie(int size); 7 bool eatCookie(Cookie * cookie); 1 // Interface 1 2 Cookie * makeCookie(int size); 3 bool showCookie(Cookie * cookie); 4 5 // Interface 2 6 Cookie * getCookie(int size); 7 bool eatCookie(Cookie * cookie);
  • 19. Приклад “Інтерфейс” 3 1 // Interface 1 2 Cookie * makeCookie(int size); 3 bool showCookie(Cookie * cookie); 4 5 // Interface 2 6 Cookie * getCookie(int size); 7 bool eatCookie(Cookie * cookie); 1 // Interface 1 2 std::unique_ptr<Cookie> makeCookie(int size); 3 bool showCookie(Cookie * cookie); 4 5 // Interface 2 6 Cookie * getCookie(int size); 7 bool eatCookie(std::unique_ptr<Cookie> && cookie);
  • 20. Приклад “Інтерфейс” 4 1 // Interface 1 2 std::unique_ptr<Cookie> makeCookie(int size); 3 bool showCookie(std::observer_ptr<Cookie> cookie); 4 // std::observer_ptr may land in C++2x 5 // Interface 2 6 std::observer_ptr<Cookie> getCookie(int size); 7 bool eatCookie(std::unique_ptr<Cookie> && cookie); 1 // Interface 1 2 std::unique_ptr<Cookie> makeCookie(int size); 3 bool showCookie(Cookie * cookie); 4 5 // Interface 2 6 Cookie * getCookie(int size); 7 bool eatCookie(std::unique_ptr<Cookie> && cookie);
  • 21. Приклад “Користувач” 3 2 std::unique_ptr<Cookie> makeCookie(int size); 7 bool eatCookie(std::unique_ptr<Cookie> && cookie); 1 auto cookie = makeCookie(47); 2 cookie->coverWithCream(); 3 if (eatCookie(std::move(cookie))) 4 std::cout << "Yum!n";
  • 22. Приклад “Користувач” 1 2 Cookie * makeCookie(int size); 7 bool eatCookie(Cookie * cookie); 1 auto * cookie = makeCookie(47); 2 try { 3 cookie->coverWithCream(); 4 } 5 catch (...) { 6 delete cookie; 7 throw; 8 } 9 if (eatCookie(cookie)) { 10 std::cout << "Yum!n"; 11 cookie = nullptr; 12 } 13 else 14 delete cookie;
  • 23. Ефективність unique_ptr  Реалізація unique_ptr використовує Empty base optimization (EBO)  Кожна операція над unique_ptr теоретично повинна бути такою ж швидкою, як відповідна операція над “голим” вказівником  template <class T, class Deleter = std::default_delete<T>>  class unique_ptr;  sizeof(std::unique_ptr<T, Deleter>) == sizeof(T *)  // (якщо Deleter — порожній клас)
  • 24. unique_ptr чи стек?  Варто оголошувати об'єкти на стеку у функціях та за значенням у класах коли це можливо: вбудовані типи, класи стандартної бібліотеки, інші прості структури та класи. Це простіше і ефективніше.  Поліморфний об'єкт  Вказівник на реалізацію (класу) == Pointer to implementation == Pimpl idiom == Opaque pointer
  • 25. unique_ptr чи стек? (2)  Потрібен стан відсутності - nullptr (краще std::optional із C++17)  Адреса об'єкта повинна бути сталою, але власник об'єкта може змінюватись  Переміщення об'єкту повільне або неможливе  Потрібне особливе видалення (custom deleter)
  • 26. Приклад “Особливе видалення” 1 // Interface 2 struct IppDeleter 3 { 4 void operator()(Ipp64f * p) const { ippsFree(p); } 5 }; 6 7 using Ipp64fUniquePtr = std::unique_ptr<Ipp64f, IppDeleter>; 8 9 inline Ipp64fUniquePtr makeUniqueIpp64f(int len) 10 { 11 return Ipp64fUniquePtr(ippsMalloc_64f(len)); 12 } 13 14 // Usage 15 auto factor = makeUniqueIpp64f(3);
  • 27. Приклад make_unique (C++14) 1 // Interface 2 void combine(std::unique_ptr<A> && a, std::unique_pr<B> && b); 1 // Usage 1 (exception unsafe because of a possible interleaved order of 2 // execution of subexpressions in function parameters) 3 combine(std::unique_ptr<A>(new A(2)), std::unique_ptr<B>(new B)); 4 combine(std::unique_ptr<A>(new A(2)), createB()); 1 // Usage 2 (exception safe) 2 combine(std::make_unique<A>(2), std::make_unique<B>()); 3 combine(std::make_unique<A>(2), createB());
  • 28. Приклад make_unique 2 (C++14) 1 // Declaration 2 std::vector<std::unique_ptr<Biscuit>> biscuits; 1 // Usage 1 (line 2 is long; line 3 is exception unsafe: if emplace_back throws) 2 biscuits.push_back(std::unique_ptr<Biscuit>(new Biscuit)); 3 biscuits.emplace_back(new Biscuit); 1 // Usage 2 (exception safe) 2 biscuits.push_back(std::make_unique<Biscuit>()); 3 biscuits.emplace_back(std::make_unique<Biscuit>()); 1 // "Naked" declaration 2 std::vector<Biscuit *> biscuits; 1 // "Naked" usage 1 (exception unsafe) 2 biscuits.push_back(new Biscuit); 1 // "Naked" usage 2 (exception safe) 2 biscuits.push_back(nullptr); 3 biscuits.back() = new Biscuit;  Як щодо асоціативних контейнерів? (std::set, std::map, std::unordered_set , std::multimap, ...)
  • 29. std::auto_ptr  Доступний в C++98  Не інтуїтивна семантика копіювання  Не може бути використаний в контейнерах  Deprecated in C++11  Removed in C++17  Може бути легко замінений на unique_ptr
  • 30. Приклад “Вказівник на реалізацію” 1 // Spacer.h 2 class Spacer 3 { 4 public: 5 Spacer(); 6 ~Spacer(); 7 // ... 8 private: 9 class Impl; 10 std::unique_ptr<Impl> impl_; 11 }; 12 13 // Spacer.cpp 14 class Spacer::Impl 15 { 16 // ... 17 }; 18 Spacer::Spacer() : impl_(std::make_unique<Impl>()) {} 19 // Destructor definition must be in the cpp file because the 20 // implicitly invoked Impl's destructor needs complete type 21 Spacer::~Spacer() = default;
  • 31. Спеціалізація для масивів  Зазвичай std::vector або std::string зручніші.  Функція, яку не можна змінити (бібліотечна функція), приймає/вертає вказівник на масив  unique_ptr<T[]> ефективніший в деяких ситуаціях:  new T[n] виділяє пам'ять для рівно n елементів  new T[n] не ініціює елементи, якщо T - POD  template <class T, class Deleter> class unique_ptr<T[], Deleter>;