C++ без new и delete 
Матросов Михаил 
mikhail.matrosov@gmail.com 
Russian C++ User Group, Саратов, 2014
Вместо содержания 
• Что? 
– Писать код без new и delete в современном С++ 
• Как? 
– Контейнеры STL 
– std::make_shared, std::make_unique 
– Cвои обёртки для своих умных указателей 
• Почему? 
– new и delete увеличивают сложность кода 
Матросов Михаил, С++ без new и delete, 
Russian C++ User Group, Саратов, 2014 
2
Современный С++ 
• Современный С++ включает 
– Возможности стандарта С++14 
– Современные best practices 
• C++14 is done! 
– Рабочий черновик стандарта ISO/IEC 
14882:2014(E) единогласно одобрен 
– Полностью или частично поддерживается 
всеми мажорными компиляторами 
Матросов Михаил, С++ без new и delete, 
Russian C++ User Group, Саратов, 2014 
3
Что и как? 
Общие рекомендации 
Матросов Михаил, С++ без new и delete, 
Russian C++ User Group, Саратов, 2014 
4
Объекты в С 
typedef struct ObjectTag 
{ 
// Object members 
} Object; 
int InitObject(Object* io_pObject); 
int UseObject(Object* io_pObject); 
int ClearObject(Object* io_pObject); 
void ObjectsInC() 
{ 
Object* pObject; 
pObject = malloc(sizeof(Object)); // Allocate memory 
InitObject(pObject); // Establish invariants and acquire resources 
UseObject(pObject); // Do the work 
ClearObject(pObject); // Release resources 
free(pObject); // Release memory 
// By the way: error handling :-/ 
} 
Матросов Михаил, С++ без new и delete, 
Russian C++ User Group, Саратов, 2014 
5
Объекты в С++ 
• Инкапсуляция: 
– Конструкторы 
– Деструкторы 
– Методы 
class Object 
{ 
// Object members 
public: 
Object(); // Establish invariants and acquire resources 
~Object(); // Release resources 
void Use(); // Do the work 
}; 
• Обработка ошибок: 
– Исключения 
Матросов Михаил, С++ без new и delete, 
Russian C++ User Group, Саратов, 2014 
6
Объекты в С++ 
• 2 лучше, чем 1 
– управление ресурсами 
// 1. Naive C++ style 
Object* p = new Object(); // Allocate memory 
p->Use(); // Do the work 
delete p; // Release memory 
• 3 лучше, чем 2 
– unique_ptr делает всё, что и 
auto_ptr, только лучше 
• 4 лучше, чем 3 
– основная тема доклада 
// 2. More secure C++98 with RAII 
std::auto_ptr<Object> ap(new Object()); // Allocate memory 
ap->Use(); // Do the work 
// 3. More secure C++11 with RAII 
std::unique_ptr<Object> up(new Object()); // Allocate memory 
up->Use(); // Do the work 
// 4. New bullet-proof modern C++ 
auto up2 = std::make_unique<Object>(); // Create unique object 
up2->Use(); // Do the work 
Матросов Михаил, С++ без new и delete, 
Russian C++ User Group, Саратов, 2014 
7
Разделяемые объекты в С++ 
void UseObject(Object*); // Shall retain the object 
void AcceptObject(Object*); // Shall delete the object 
void ShareObject(std::shared_ptr<Object>); // Both cases 
// Naive C++ 
Object* p = new Object(); 
p->Use(); 
UseObject(p); // Want to use object after call 
p->Use(); 
AcceptObject(p); // No longer need the object 
// C++98 & RAII 
/* No way to say this! */ 
// Modern C++ 
auto sp = std::make_shared<Object>(); 
sp->Use(); 
ShareObject(sp); // Want to use object after call 
sp->Use(); 
ShareObject(std::move(sp)); // No longer need the object 
Матросов Михаил, С++ без new и delete, 
Russian C++ User Group, Саратов, 2014 
8
Объекты со счётчиком ссылок в С++ 
// Naive C++ (not used) 
RefCounted* p = new RefCounted(); 
p->AddRef(); 
p->Use(); 
p->Release(); 
// C++98 & RAII 
RefPtr<RefCounted> rp = new RefCounted(); 
rp->Use(); 
// Modern C++ 
auto rp2 = MakeRefPtr<RefCounted>(); 
rp2->Use(); 
Матросов Михаил, С++ без new и delete, 
Russian C++ User Group, Саратов, 2014 
9
Динамические массивы в С++ 
void UseArray(int*); 
int n = 100; 
// Naive C++ 
int* p = new int[n]; 
UseArray(p); 
delete[] p; 
// C++98 & RAII 
std::vector<int> v(n); 
UseArray(&v[0]); 
// Modern C++ 
std::vector<int> v2(n); 
UseArray(v2.data()); 
Матросов Михаил, С++ без new и delete, 
Russian C++ User Group, Саратов, 2014 
10
Почему? 
Аргументация 
Матросов Михаил, С++ без new и delete, 
Russian C++ User Group, Саратов, 2014 
11
Лучше == проще 
• Немного авторитета: 
– Главный технический императив разработки ПО – 
управление сложностью [McConnel2004] 
– Make Simple Tasks Simple! [Stroustrup2014] 
– ≈99.9998% разработчиков – не эксперты [Sutter2014] 
– Принцип KISS (Keep It Simple, Stupid) 
• Что значит проще? 
– Простые задачи должны решаться просто 
– Сложные – не сложнее, чем необходимо 
– Сначала – простота, затем – производительность 
• Как сделать проще? 
– Принцип DRY (Don’t Repeat Yourself) 
– Принцип «по умолчанию» [Sutter2014] 
Матросов Михаил, С++ без new и delete, 
Russian C++ User Group, Саратов, 2014 
12
Принцип «по умолчанию» 
• Основная мысль: 
– Известная задача ⇒ известное решение 
• Преимущества: 
– Взаимопонимание с другими разработчиками 
– Уменьшение порога входа для новичков 
– Меньше думать – продуктивная лень  
– Все те же, что и для правил кодирования 
• “A tour of C++” [Stroustrup2013] 
Матросов Михаил, С++ без new и delete, 
Russian C++ User Group, Саратов, 2014 
13
std::make_unique<T>() vs. 
std::unique_ptr(new T) 
int GenerateId(); 
std::pair<std::unique_ptr<Object>, int> MakeObjectWithIdWrong() 
{ 
return std::make_pair( 
std::unique_ptr<Object>(new Object()), 
GenerateId()); 
} 
std::pair<std::unique_ptr<Object>, int> MakeObjectWithIdRight() 
{ 
return std::make_pair( 
std::make_unique<Object>(), // Safe 
GenerateId()); 
} 
Дублирование 
имени типа. DRY! 
Матросов Михаил, С++ без new и delete, 
Russian C++ User Group, Саратов, 2014 
14 
// May throw 
// May leak!
std::make_shared<T>() vs. 
std::shared_ptr(new T) 
std::shared_ptr<Object> sp(new Object()); 
counter 
Object 
sp 
Два выделения 
памяти 
Матросов Михаил, С++ без new и delete, 
Russian C++ User Group, Саратов, 2014 
15
std::make_shared<T>() vs. 
std::shared_ptr(new T) 
auto sp = std::make_shared<Object>(); 
Одно выделение памяти. 
Оптимизация We Know Where 
You Live [Lavavej2012]. 
counter Object 
sp 
Матросов Михаил, С++ без new и delete, 
Russian C++ User Group, Саратов, 2014 
16
std::make_shared и std::make_unique 
• Плюсы обоих: 
– Безопасность при исключениях 
– Нет дублирования имени типа 
• Плюсы std::make_shared: 
– Одно обращение к менеджеру памяти 
• Минусы есть, но несущественные: 
– Нет формы для указания собственного аллокатора для std::unique_ptr 
(для std::shared_ptr это std::allocated_shared) 
– Опасность false sharing объекта и счётчика ссылок 
[см. вопрос на StackOverflow] 
Матросов Михаил, С++ без new и delete, 
Russian C++ User Group, Саратов, 2014 
17
Обобщаем 
• delete по умолчанию не используется со 
времён RAII и стандартных контейнеров 
• new по умолчанию не используется при работе 
со стандартной библиотекой 
• Постараемся не использовать new при работе 
с другими библиотеками 
– Свои объекты со счётчиком ссылок 
– Свои умные указатели 
– Своё управление памятью 
• Теперь и new по умолчанию не используется 
Матросов Михаил, С++ без new и delete, 
Russian C++ User Group, Саратов, 2014 
18
Как? 
Некоторые подробности использования 
Матросов Михаил, С++ без new и delete, 
Russian C++ User Group, Саратов, 2014 
19
Объекты со счётчиком ссылок 
• OpenSceneGraph 
– Открытый 3D-движок под OpenGL на С++ 
– osg::Referenced – класс со счётчиком ссылок, 
базовый для большинства классов 
• ref() увеличивает счётчик 
• unref() уменьшает счётчик и удаляет объект если 
счётчик становится равен нулю 
– osg::ref_ptr<T> – умный указатель 
• вызывает ref() в конструкторе 
• вызывает unref() в деструкторе 
Матросов Михаил, С++ без new и delete, 
Russian C++ User Group, Саратов, 2014 
20
OSG: C++ & RAII 
• Пример кода из [Wang2010, стр. 78] 
• Идеально подходит для апгрейда 
– Может быть выполнен автоматически 
osg::ref_ptr<osg::Vec3Array> vertices = new osg::Vec3Array; 
// Init vertices 
osg::ref_ptr<osg::Vec3Array> normals = new osg::Vec3Array; 
// Init normals 
osg::ref_ptr<osg::Geometry> geom = new osg::Geometry; 
geom->setVertexArray(vertices.get()); 
geom->setNormalArray(normals.get()); 
// Further init geometry and use it 
Матросов Михаил, С++ без new и delete, 
Russian C++ User Group, Саратов, 2014 
21
OSG: Modern C++ 
namespace osg 
{ 
template<typename T, typename... Args> 
osg::ref_ptr<T> make_ref(Args&&... args) 
{ 
return new T(std::forward<Args>(args)...); 
} 
} 
auto vertices = osg::make_ref<osg::Vec3Array>(); 
// Init vertices 
auto normals = osg::make_ref<osg::Vec3Array>(); 
// Init normals 
auto geom = osg::make_ref<osg::Geometry>(); 
geom->setVertexArray(vertices.get()); 
geom->setNormalArray(normals.get()); 
// Further init geometry and use it 
Матросов Михаил, С++ без new и delete, 
Russian C++ User Group, Саратов, 2014 
22
Своё управление памятью 
• Qt 
– Cross-platform application and UI framework 
– QObject – класс, устанавливающий отношение 
родства, базовый для большинства классов 
• Имеет список детей, удаляет их в своём деструкторе 
• Имеет ссылку на родителя, которая может быть null 
• Может менять родителя в процессе жизни 
– QSharedPointer – аналог std::shared_ptr 
• Предоставляет QSharedPointer<T>::create() по 
аналогии с std::make_shared<T>() 
Матросов Михаил, С++ без new и delete, 
Russian C++ User Group, Саратов, 2014 
23
QObject 
• Сценарии использования: 
– Создание объекта в стеке 
• Удаляется при выходе из блока 
– Динамическое создание объекта с родителем 
• Удаляется родителем 
– Динамическое создание объекта без родителя 
• Нужно указать родителя или удалить вручную 
Матросов Михаил, С++ без new и delete, 
Russian C++ User Group, Саратов, 2014 
24
Qt::MakeChild 
• Обёртка для безопасного сценария (см. 
обсуждение). 
• Теперь new означает небезопасный сценарий 
namespace Qt 
{ 
template<class T, class... Args> 
T* MakeChild(Args&&... args) 
{ 
T* pObject = new T(std::forward<Args>(args)...); 
Q_ASSERT(pObject->parent() != nullptr); 
return pObject; 
} 
} 
Матросов Михаил, С++ без new и delete, 
Russian C++ User Group, Саратов, 2014 
25
Qt::MakeChild 
MyWidget::MyWidget() 
{ 
// Safe, created on the stack 
QProgressDialog progress("In progress...", "Cancel", 0, 100); 
// Safe, parent is specified 
{ 
// Regular, valid since C++98 
QPushButton* pButton = new QPushButton("Push me", this); 
// Proposed, modern C++ style 
auto pButton2 = Qt::MakeChild<QPushButton>("And me", this); 
} 
// Unsafe, parent is null, need manual delete 
m_pDialog = new QDialog(); 
} 
Матросов Михаил, С++ без new и delete, 
Russian C++ User Group, Саратов, 2014 
26
Необходимые возможности С++14 
• Возможности языка: 
– Точная передача (perfect forwarding) 
– Шаблоны с переменным количеством 
параметров (variadic templates) 
• Возможности стандартной библиотеки: 
– Умные указатели 
– std::make_shared, std::make_unique 
Матросов Михаил, С++ без new и delete, 
Russian C++ User Group, Саратов, 2014 
27 
Можно обойтись 
и без них 
Можно написать 
самому
Заключение 
• Хороший код – простой код 
• Принцип «по умолчанию» для упрощения 
• Проблемы с delete давно известны 
• Для стандартной библиотеки код без new 
лучше, это объявляется подходом по 
умолчанию – для упрощения 
• new и delete теперь ассоциируются с 
небезопасными операциями 
Матросов Михаил, С++ без new и delete, 
Russian C++ User Group, Саратов, 2014 
28
Спасибо за внимание! 
Матросов Михаил, С++ без new и delete, 
Russian C++ User Group, Саратов, 2014 
29
Библиография 
[McConnell2004] McConnell, Steve, and Detlef Johannis. Code 
complete. Vol. 2. Redmond: Microsoft press, 2004. 
[Wang2010]Wang, Rui, and Xuelei Qian. OpenSceneGraph 3.0: 
Beginner's guide. Packt Publishing Ltd, 2010. 
[Lavavej2012] Lavavej, Stephan. STL11: Magic && Secrets. Going 
Native, 2012. 
[Stroustrup2013] Stroustrup, Bjarne. A Tour of C++. Addison- 
Wesley, 2013. 
[Stroustrup2014] Stroustrup, Bjarne. Make Simple Tasks Simple! 
CppCon, 2014. 
[Sutter2014] Sutter, Herb. Back to the Basics! Essentials of 
Modern C++ Style. CppCon, 2014. 
Матросов Михаил, С++ без new и delete, 
Russian C++ User Group, Саратов, 2014 
30
Принцип «по умолчанию» 
Задача Решение по умолчанию 
Передача параметров в функцию Pass by value or const& 
См. [Sutter2014] 
Возврат параметров из функции Return by value 
См. [Sutter2014] 
Массив произвольного размера? 
Массив изменяющегося размера? 
Список произвольных объектов? 
std::vector 
Массив фиксированного размера std::array 
Действие над каждым элементом 
контейнера 
range-based for 
Автоматическое управление 
динамической памятью 
std::make_unique или std::make_shared 
Матросов Михаил, С++ без new и delete, 
Russian C++ User Group, Саратов, 2014 
31
Выражение намерения 
• Что сделать, а не как сделать 
• Более высокоуровневый код 
Матросов Михаил, С++ без new и delete, 
Russian C++ User Group, Саратов, 2014 
32
Память – ресурс 
std∷make_unique 
new/delete 
= 
new/delete 
malloc/free 
= 
std∷fstream 
fopen/fclose 
Матросов Михаил, С++ без new и delete, 
Russian C++ User Group, Саратов, 2014 
33

Михаил Матросов, “С++ без new и delete”

  • 1.
    C++ без newи delete Матросов Михаил mikhail.matrosov@gmail.com Russian C++ User Group, Саратов, 2014
  • 2.
    Вместо содержания •Что? – Писать код без new и delete в современном С++ • Как? – Контейнеры STL – std::make_shared, std::make_unique – Cвои обёртки для своих умных указателей • Почему? – new и delete увеличивают сложность кода Матросов Михаил, С++ без new и delete, Russian C++ User Group, Саратов, 2014 2
  • 3.
    Современный С++ •Современный С++ включает – Возможности стандарта С++14 – Современные best practices • C++14 is done! – Рабочий черновик стандарта ISO/IEC 14882:2014(E) единогласно одобрен – Полностью или частично поддерживается всеми мажорными компиляторами Матросов Михаил, С++ без new и delete, Russian C++ User Group, Саратов, 2014 3
  • 4.
    Что и как? Общие рекомендации Матросов Михаил, С++ без new и delete, Russian C++ User Group, Саратов, 2014 4
  • 5.
    Объекты в С typedef struct ObjectTag { // Object members } Object; int InitObject(Object* io_pObject); int UseObject(Object* io_pObject); int ClearObject(Object* io_pObject); void ObjectsInC() { Object* pObject; pObject = malloc(sizeof(Object)); // Allocate memory InitObject(pObject); // Establish invariants and acquire resources UseObject(pObject); // Do the work ClearObject(pObject); // Release resources free(pObject); // Release memory // By the way: error handling :-/ } Матросов Михаил, С++ без new и delete, Russian C++ User Group, Саратов, 2014 5
  • 6.
    Объекты в С++ • Инкапсуляция: – Конструкторы – Деструкторы – Методы class Object { // Object members public: Object(); // Establish invariants and acquire resources ~Object(); // Release resources void Use(); // Do the work }; • Обработка ошибок: – Исключения Матросов Михаил, С++ без new и delete, Russian C++ User Group, Саратов, 2014 6
  • 7.
    Объекты в С++ • 2 лучше, чем 1 – управление ресурсами // 1. Naive C++ style Object* p = new Object(); // Allocate memory p->Use(); // Do the work delete p; // Release memory • 3 лучше, чем 2 – unique_ptr делает всё, что и auto_ptr, только лучше • 4 лучше, чем 3 – основная тема доклада // 2. More secure C++98 with RAII std::auto_ptr<Object> ap(new Object()); // Allocate memory ap->Use(); // Do the work // 3. More secure C++11 with RAII std::unique_ptr<Object> up(new Object()); // Allocate memory up->Use(); // Do the work // 4. New bullet-proof modern C++ auto up2 = std::make_unique<Object>(); // Create unique object up2->Use(); // Do the work Матросов Михаил, С++ без new и delete, Russian C++ User Group, Саратов, 2014 7
  • 8.
    Разделяемые объекты вС++ void UseObject(Object*); // Shall retain the object void AcceptObject(Object*); // Shall delete the object void ShareObject(std::shared_ptr<Object>); // Both cases // Naive C++ Object* p = new Object(); p->Use(); UseObject(p); // Want to use object after call p->Use(); AcceptObject(p); // No longer need the object // C++98 & RAII /* No way to say this! */ // Modern C++ auto sp = std::make_shared<Object>(); sp->Use(); ShareObject(sp); // Want to use object after call sp->Use(); ShareObject(std::move(sp)); // No longer need the object Матросов Михаил, С++ без new и delete, Russian C++ User Group, Саратов, 2014 8
  • 9.
    Объекты со счётчикомссылок в С++ // Naive C++ (not used) RefCounted* p = new RefCounted(); p->AddRef(); p->Use(); p->Release(); // C++98 & RAII RefPtr<RefCounted> rp = new RefCounted(); rp->Use(); // Modern C++ auto rp2 = MakeRefPtr<RefCounted>(); rp2->Use(); Матросов Михаил, С++ без new и delete, Russian C++ User Group, Саратов, 2014 9
  • 10.
    Динамические массивы вС++ void UseArray(int*); int n = 100; // Naive C++ int* p = new int[n]; UseArray(p); delete[] p; // C++98 & RAII std::vector<int> v(n); UseArray(&v[0]); // Modern C++ std::vector<int> v2(n); UseArray(v2.data()); Матросов Михаил, С++ без new и delete, Russian C++ User Group, Саратов, 2014 10
  • 11.
    Почему? Аргументация МатросовМихаил, С++ без new и delete, Russian C++ User Group, Саратов, 2014 11
  • 12.
    Лучше == проще • Немного авторитета: – Главный технический императив разработки ПО – управление сложностью [McConnel2004] – Make Simple Tasks Simple! [Stroustrup2014] – ≈99.9998% разработчиков – не эксперты [Sutter2014] – Принцип KISS (Keep It Simple, Stupid) • Что значит проще? – Простые задачи должны решаться просто – Сложные – не сложнее, чем необходимо – Сначала – простота, затем – производительность • Как сделать проще? – Принцип DRY (Don’t Repeat Yourself) – Принцип «по умолчанию» [Sutter2014] Матросов Михаил, С++ без new и delete, Russian C++ User Group, Саратов, 2014 12
  • 13.
    Принцип «по умолчанию» • Основная мысль: – Известная задача ⇒ известное решение • Преимущества: – Взаимопонимание с другими разработчиками – Уменьшение порога входа для новичков – Меньше думать – продуктивная лень  – Все те же, что и для правил кодирования • “A tour of C++” [Stroustrup2013] Матросов Михаил, С++ без new и delete, Russian C++ User Group, Саратов, 2014 13
  • 14.
    std::make_unique<T>() vs. std::unique_ptr(newT) int GenerateId(); std::pair<std::unique_ptr<Object>, int> MakeObjectWithIdWrong() { return std::make_pair( std::unique_ptr<Object>(new Object()), GenerateId()); } std::pair<std::unique_ptr<Object>, int> MakeObjectWithIdRight() { return std::make_pair( std::make_unique<Object>(), // Safe GenerateId()); } Дублирование имени типа. DRY! Матросов Михаил, С++ без new и delete, Russian C++ User Group, Саратов, 2014 14 // May throw // May leak!
  • 15.
    std::make_shared<T>() vs. std::shared_ptr(newT) std::shared_ptr<Object> sp(new Object()); counter Object sp Два выделения памяти Матросов Михаил, С++ без new и delete, Russian C++ User Group, Саратов, 2014 15
  • 16.
    std::make_shared<T>() vs. std::shared_ptr(newT) auto sp = std::make_shared<Object>(); Одно выделение памяти. Оптимизация We Know Where You Live [Lavavej2012]. counter Object sp Матросов Михаил, С++ без new и delete, Russian C++ User Group, Саратов, 2014 16
  • 17.
    std::make_shared и std::make_unique • Плюсы обоих: – Безопасность при исключениях – Нет дублирования имени типа • Плюсы std::make_shared: – Одно обращение к менеджеру памяти • Минусы есть, но несущественные: – Нет формы для указания собственного аллокатора для std::unique_ptr (для std::shared_ptr это std::allocated_shared) – Опасность false sharing объекта и счётчика ссылок [см. вопрос на StackOverflow] Матросов Михаил, С++ без new и delete, Russian C++ User Group, Саратов, 2014 17
  • 18.
    Обобщаем • deleteпо умолчанию не используется со времён RAII и стандартных контейнеров • new по умолчанию не используется при работе со стандартной библиотекой • Постараемся не использовать new при работе с другими библиотеками – Свои объекты со счётчиком ссылок – Свои умные указатели – Своё управление памятью • Теперь и new по умолчанию не используется Матросов Михаил, С++ без new и delete, Russian C++ User Group, Саратов, 2014 18
  • 19.
    Как? Некоторые подробностииспользования Матросов Михаил, С++ без new и delete, Russian C++ User Group, Саратов, 2014 19
  • 20.
    Объекты со счётчикомссылок • OpenSceneGraph – Открытый 3D-движок под OpenGL на С++ – osg::Referenced – класс со счётчиком ссылок, базовый для большинства классов • ref() увеличивает счётчик • unref() уменьшает счётчик и удаляет объект если счётчик становится равен нулю – osg::ref_ptr<T> – умный указатель • вызывает ref() в конструкторе • вызывает unref() в деструкторе Матросов Михаил, С++ без new и delete, Russian C++ User Group, Саратов, 2014 20
  • 21.
    OSG: C++ &RAII • Пример кода из [Wang2010, стр. 78] • Идеально подходит для апгрейда – Может быть выполнен автоматически osg::ref_ptr<osg::Vec3Array> vertices = new osg::Vec3Array; // Init vertices osg::ref_ptr<osg::Vec3Array> normals = new osg::Vec3Array; // Init normals osg::ref_ptr<osg::Geometry> geom = new osg::Geometry; geom->setVertexArray(vertices.get()); geom->setNormalArray(normals.get()); // Further init geometry and use it Матросов Михаил, С++ без new и delete, Russian C++ User Group, Саратов, 2014 21
  • 22.
    OSG: Modern C++ namespace osg { template<typename T, typename... Args> osg::ref_ptr<T> make_ref(Args&&... args) { return new T(std::forward<Args>(args)...); } } auto vertices = osg::make_ref<osg::Vec3Array>(); // Init vertices auto normals = osg::make_ref<osg::Vec3Array>(); // Init normals auto geom = osg::make_ref<osg::Geometry>(); geom->setVertexArray(vertices.get()); geom->setNormalArray(normals.get()); // Further init geometry and use it Матросов Михаил, С++ без new и delete, Russian C++ User Group, Саратов, 2014 22
  • 23.
    Своё управление памятью • Qt – Cross-platform application and UI framework – QObject – класс, устанавливающий отношение родства, базовый для большинства классов • Имеет список детей, удаляет их в своём деструкторе • Имеет ссылку на родителя, которая может быть null • Может менять родителя в процессе жизни – QSharedPointer – аналог std::shared_ptr • Предоставляет QSharedPointer<T>::create() по аналогии с std::make_shared<T>() Матросов Михаил, С++ без new и delete, Russian C++ User Group, Саратов, 2014 23
  • 24.
    QObject • Сценариииспользования: – Создание объекта в стеке • Удаляется при выходе из блока – Динамическое создание объекта с родителем • Удаляется родителем – Динамическое создание объекта без родителя • Нужно указать родителя или удалить вручную Матросов Михаил, С++ без new и delete, Russian C++ User Group, Саратов, 2014 24
  • 25.
    Qt::MakeChild • Обёрткадля безопасного сценария (см. обсуждение). • Теперь new означает небезопасный сценарий namespace Qt { template<class T, class... Args> T* MakeChild(Args&&... args) { T* pObject = new T(std::forward<Args>(args)...); Q_ASSERT(pObject->parent() != nullptr); return pObject; } } Матросов Михаил, С++ без new и delete, Russian C++ User Group, Саратов, 2014 25
  • 26.
    Qt::MakeChild MyWidget::MyWidget() { // Safe, created on the stack QProgressDialog progress("In progress...", "Cancel", 0, 100); // Safe, parent is specified { // Regular, valid since C++98 QPushButton* pButton = new QPushButton("Push me", this); // Proposed, modern C++ style auto pButton2 = Qt::MakeChild<QPushButton>("And me", this); } // Unsafe, parent is null, need manual delete m_pDialog = new QDialog(); } Матросов Михаил, С++ без new и delete, Russian C++ User Group, Саратов, 2014 26
  • 27.
    Необходимые возможности С++14 • Возможности языка: – Точная передача (perfect forwarding) – Шаблоны с переменным количеством параметров (variadic templates) • Возможности стандартной библиотеки: – Умные указатели – std::make_shared, std::make_unique Матросов Михаил, С++ без new и delete, Russian C++ User Group, Саратов, 2014 27 Можно обойтись и без них Можно написать самому
  • 28.
    Заключение • Хорошийкод – простой код • Принцип «по умолчанию» для упрощения • Проблемы с delete давно известны • Для стандартной библиотеки код без new лучше, это объявляется подходом по умолчанию – для упрощения • new и delete теперь ассоциируются с небезопасными операциями Матросов Михаил, С++ без new и delete, Russian C++ User Group, Саратов, 2014 28
  • 29.
    Спасибо за внимание! Матросов Михаил, С++ без new и delete, Russian C++ User Group, Саратов, 2014 29
  • 30.
    Библиография [McConnell2004] McConnell,Steve, and Detlef Johannis. Code complete. Vol. 2. Redmond: Microsoft press, 2004. [Wang2010]Wang, Rui, and Xuelei Qian. OpenSceneGraph 3.0: Beginner's guide. Packt Publishing Ltd, 2010. [Lavavej2012] Lavavej, Stephan. STL11: Magic && Secrets. Going Native, 2012. [Stroustrup2013] Stroustrup, Bjarne. A Tour of C++. Addison- Wesley, 2013. [Stroustrup2014] Stroustrup, Bjarne. Make Simple Tasks Simple! CppCon, 2014. [Sutter2014] Sutter, Herb. Back to the Basics! Essentials of Modern C++ Style. CppCon, 2014. Матросов Михаил, С++ без new и delete, Russian C++ User Group, Саратов, 2014 30
  • 31.
    Принцип «по умолчанию» Задача Решение по умолчанию Передача параметров в функцию Pass by value or const& См. [Sutter2014] Возврат параметров из функции Return by value См. [Sutter2014] Массив произвольного размера? Массив изменяющегося размера? Список произвольных объектов? std::vector Массив фиксированного размера std::array Действие над каждым элементом контейнера range-based for Автоматическое управление динамической памятью std::make_unique или std::make_shared Матросов Михаил, С++ без new и delete, Russian C++ User Group, Саратов, 2014 31
  • 32.
    Выражение намерения •Что сделать, а не как сделать • Более высокоуровневый код Матросов Михаил, С++ без new и delete, Russian C++ User Group, Саратов, 2014 32
  • 33.
    Память – ресурс std∷make_unique new/delete = new/delete malloc/free = std∷fstream fopen/fclose Матросов Михаил, С++ без new и delete, Russian C++ User Group, Саратов, 2014 33