- Фантастика и фэнтези
- Ироническое фэнтези
- Стимпанк
- Детективная фантастика
- Киберпанк
- Попаданцы
- LitRPG
- Космоопера
- Технофэнтези
- Городская фантастика
- Русское фэнтези
- Юмористическая фантастика
- Космическая фантастика
- Боевое фэнтези
- Эпическая фантастика
- Зарубежная фантастика
- Книги магов
- Мистика
- Разная фантастика
- Разное фэнтези
- Любовное фэнтези
- Романтическая фантастика
- Городское фентези
- Историческая фантастика
- Историческое фэнтези
- Социально-философская фантастика
- Сказочная фантастика
- Иностранное фэнтези
- Романтическое фэнтези
- Ироническая фантастика
- Ужасы и Мистика
- Постапокалипсис
- Героическая фантастика
- Фэнтези
- Научная Фантастика
- Социально-психологическая
- Альтернативная история
- Боевая фантастика
- Разная литература
- Пословицы, поговорки
- Шахматы
- Визуальные искусства
- Фанфик
- Авто и ПДД
- Военное
- Отраслевые издания
- Гиды, путеводители
- Зарубежная образовательная литература
- Военная история
- Цитаты из афоризмов
- Современная литература
- Великолепные истории
- Начинающие авторы
- Современная зарубежная литература
- Боевые искусства
- Изобразительное искусство, фотография
- Кино
- Литература 19 века
- Недвижимость
- Музыка, музыканты
- Готические новеллы
- Истории из жизни
- Культура и искусство
- Спецслужбы
- Зарубежная прикладная литература
- Музыка, танцы
- Подростковая литература
- Прочее
- Военная техника, оружие
- Газеты и журналы
- Периодические издания
- Домоводство, Дом и семья
- Любовные романы
- Экономическая литература
- Научные и научно-популярные книги
- О животных
- Биохимия
- Культурология
- Юриспруденция
- Политика
- Психотерапия
- Языкознание
- Научпоп
- Медицина
- Психология, личное
- Радиотехника
- Филология
- Педагогика
- Образовательная литература
- Деловая литература
- Физика
- Науки: разное
- Химия
- Воспитание детей, педагогика
- Детская психология
- Зарубежная публицистика
- Биология
- Архитектура
- Зарубежная психология
- Науки о космосе
- Социология
- Математика
- География
- Беременность, ожидание детей
- Литературоведение
- Транспорт, военная техника
- Обществознание
- Зоология
- География
- Альтернативная медицина
- Иностранные языки
- Ветеринария
- Рефераты
- Астрология
- Биофизика
- Экология
- История Европы
- Учебники
- Шпаргалки
- Государство и право
- Ботаника
- Религиоведение
- История
- Техническая литература
- Прочая научная литература
- Психология
- Детективы и Триллеры
- Справочная литература
- Проза
- Новелла
- Юмор
- Проза
- Историческая проза
- Русская современная проза
- Советская классическая проза
- Повести
- Очерки
- Эссе
- Рассказы
- Зарубежная современная проза
- Сентиментальная проза
- Зарубежная классика
- Афоризмы
- Эпистолярная проза
- Феерия
- Семейный роман/Семейная сага
- Разное
- Антисоветская литература
- Магический реализм
- Русская классическая проза
- Современная проза
- О войне
- Контркультура
- Классическая проза
- Поэзия, Драматургия
- Детская литература
- Детская фантастика
- Детские остросюжетные
- Детские стихи
- Детские приключения
- Внеклассное чтение
- Учебная литература
- Зарубежные детские книги
- Бизнес
- Загадки
- Книги для подростков
- Школьные учебники
- Детский фольклор
- Книги для дошкольников
- Детские детективы
- Детская познавательная и развивающая литература
- Буквари
- Прочая детская литература
- Сказка
- Детская проза
- Детская образовательная литература
- Юмор
- Документальные книги
- Бизнес
- Внешнеэкономическая деятельность
- Тайм-менеджмент
- Кадровый менеджмент
- О бизнесе популярно
- Управление, подбор персонала
- Бизнес
- Менеджмент и кадры
- Продажи
- Экономика
- Ценные бумаги и инвестиции
- Малый бизнес
- Делопроизводство, офис
- Корпоративная культура, бизнес
- Банковское дело
- Финансы
- Зарубежная деловая литература
- Ораторское искусство / риторика
- Личные финансы
- Интернет-бизнес
- Поиск работы
- Государственное и муниципальное управление
- Бухучет и аудит
- Работа с клиентами
- Менеджмент
- Краткое содержание
- Личная эффективность
- Переговоры
- Приключения
- Старинная литература
- Религия и духовность
- Компьютеры и Интернет
- Блог
Читаем без скачивания C++17 STL Стандартная библиотека шаблонов - Яцек Галовиц
Шрифт:
Интервал:
Закладка:
Поскольку существуют структуры данных, такие как unique_ptr и shared_ ptr, необходимость создавать объекты в куче вручную с помощью ключевых слов new и delete возникает редко. Используйте эти классы везде, где возможно! unique_ptr не создает никаких лишних издержек во время выполнения.
Автоматическое управление разделяемой памятью кучи с использованием std::shared_ptr
В предыдущем примере мы узнали, как использовать unique_ptr. Это очень полезный и важный класс, поскольку помогает нам управлять объектами, память для которых выделяется динамически. Однако он может владеть объектом только единолично. Нельзя сделать так, чтобы несколько объектов данного класса обладали одним динамически выделенным объектом, поскольку будет непонятно, кто именно должен удалить его.
Тип указателя shared_ptr был разработан специально для этого случая. Общие указатели могут быть скопированы любое количество раз. Внутренний механизм подсчета ссылок отслеживает, сколько объектов все еще содержат указатель на объект. Только последний общий указатель, выходящий за пределы области видимости, может удалить объект. Таким образом, можно быть уверенными в том, что утечек памяти не возникнет, поскольку объекты удаляются автоматически после использования, как и в том, что они не будут удаляться слишком рано или слишком часто (каждый созданный объект должен быть удален всего один раз).
В этом примере вы узнаете, как использовать shared_ptr для автоматического управления динамическими объектами, которые имеют несколько владельцев, и увидите, чем общие указатели отличаются от unique_ptr:.
Как это делается
В этом примере мы напишем программу, похожую на ту, которую мы писали в предыдущем примере, чтобы освоить основные принципы использования общих указателей.
1. Сначала включим необходимые заголовочные файлы и объявим об использовании пространства имен std:
#include <iostream>
#include <memory>
using namespace std;
2. Затем определим небольшой вспомогательный класс, который поможет увидеть, когда его экземпляры будут создаваться и разрушаться. Мы станем управлять его экземплярами с помощью shared_ptr:
class Foo
{
public:
string name;
Foo(string n)
: name{move(n)}
{ cout << "CTOR " << name << 'n'; }
~Foo() { cout << "DTOR " << name << 'n'; }
};
3. Далее реализуем функцию, которая принимает общий указатель на экземпляр типа Foo по значению. Передача общих указателей по значению в качестве аргументов более интересна, чем их передача по ссылке, поскольку в этом случае их нужно скопировать, что изменит их внутренний счетчик ссылок, как мы увидим далее.
void f(shared_ptr<Foo> sp)
{
cout << "f: use counter at "
<< sp.use_count() << 'n';
}
4. В функции main мы объявим пустой общий указатель. Вызвав его конструктор по умолчанию, мы сделаем его указателем null:
int main()
{
shared_ptr<Foo> fa;
5. Далее откроем еще одну область видимости и создадим два объекта типа Foo. Первый из них создадим с помощью оператора new и передадим его в конструктор типа shared_ptr. Далее создадим второй экземпляр, используя make_shared<Foo>, что позволяет создать экземпляр типа Foo на основе переданных нами параметров. Этот метод более элегантен, поскольку можно воспользоваться автоматическим выведением типов, и объект уже будет управляемым, когда у нас появится первая возможность получить к нему доступ. Это очень похоже на тот код, который мы писали в примере для unique_ptr.
{
cout << "Inner scope beginn";
shared_ptr<Foo> f1 {new Foo{"foo"}};
auto f2 (make_shared<Foo>("bar"));
6. Поскольку общие указатели могут быть разделяемыми, они должны отслеживать количество сторон, владеющих ими. Это делается с помощью внутреннего счетчика ссылок или счетчика использования. Можно вывести на экран его значение, задействуя use_count. Сейчас его значение равно 1, поскольку мы еще не копировали его. Копирование f1 в fa увеличит значение счетчика использования до 2.
cout << "f1's use counter at " << f1.use_count() << 'n';
fa = f1;
cout << "f1's use counter at " << f1.use_count() << 'n';
7. Когда мы покинем область видимости, общие указатели f1 и f2 будут уничтожены. Счетчик ссылок переменной f1 снова уменьшится до 1, что сделает fa единственным владельцем экземпляра типа Foo. При разрушении f2 его счетчик ссылок будет уменьшен до 0. В данном случае деструктор класса shared_ptr выполнит операцию delete для этого объекта, который удалит его.
}
cout << "Back to outer scopen";
cout << fa.use_count() << 'n';
8. Теперь вызовем функцию f для нашего общего указателя двумя разными способами. Сначала вызовем ее путем копирования fa. Функция f затем выведет на экран значение счетчика ссылок, которое равно 2. Во втором вызове f переместим указатель в функцию. Это сделает f единственным владельцем объекта.
cout << "first f() calln";
f(fa);
cout << "second f() calln";
f(move(fa));
9. После того как функция f отработает, экземпляр Foo будет мгновенно уничтожен, поскольку мы им больше не владеем. Поэтому все объекты подвергнутся уничтожению, когда отработает функция main.
cout << "end of main()n";
}
10. Компиляция и запуск программы дадут следующий результат. Сначала мы увидим, что созданы "foo" и "bar". После копирования f1 (указывает на "foo") его счетчик ссылок увеличился до значения 2. При выходе из области видимости "bar" уничтожается, поскольку общий указатель был его единственным владельцем. Одна единица на экране — счетчик ссылок fa, который является единственным владельцем "foo". После этого мы дважды вызываем функцию f. При первом