- Любовные романы
- Фантастика и фэнтези
- Ненаучная фантастика
- Ироническое фэнтези
- Научная Фантастика
- Фэнтези
- Ужасы и Мистика
- Боевая фантастика
- Альтернативная история
- Космическая фантастика
- Попаданцы
- Юмористическая фантастика
- Героическая фантастика
- Детективная фантастика
- Социально-психологическая
- Боевое фэнтези
- Русское фэнтези
- Киберпанк
- Романтическая фантастика
- Городская фантастика
- Технофэнтези
- Мистика
- Разная фантастика
- Иностранное фэнтези
- Историческое фэнтези
- LitRPG
- Эпическая фантастика
- Зарубежная фантастика
- Городское фентези
- Космоопера
- Разное фэнтези
- Книги магов
- Любовное фэнтези
- Постапокалипсис
- Бизнес
- Историческая фантастика
- Социально-философская фантастика
- Сказочная фантастика
- Стимпанк
- Романтическое фэнтези
- Ироническая фантастика
- Детективы и Триллеры
- Проза
- Юмор
- Феерия
- Новелла
- Русская классическая проза
- Современная проза
- Повести
- Контркультура
- Русская современная проза
- Историческая проза
- Проза
- Классическая проза
- Советская классическая проза
- О войне
- Зарубежная современная проза
- Рассказы
- Зарубежная классика
- Очерки
- Антисоветская литература
- Магический реализм
- Разное
- Сентиментальная проза
- Афоризмы
- Эссе
- Эпистолярная проза
- Семейный роман/Семейная сага
- Поэзия, Драматургия
- Приключения
- Детская литература
- Загадки
- Книга-игра
- Детская проза
- Детские приключения
- Сказка
- Прочая детская литература
- Детская фантастика
- Детские стихи
- Детская образовательная литература
- Детские остросюжетные
- Учебная литература
- Зарубежные детские книги
- Детский фольклор
- Буквари
- Книги для подростков
- Школьные учебники
- Внеклассное чтение
- Книги для дошкольников
- Детская познавательная и развивающая литература
- Детские детективы
- Домоводство, Дом и семья
- Юмор
- Документальные книги
- Бизнес
- Работа с клиентами
- Тайм-менеджмент
- Кадровый менеджмент
- Экономика
- Менеджмент и кадры
- Управление, подбор персонала
- О бизнесе популярно
- Интернет-бизнес
- Личные финансы
- Делопроизводство, офис
- Маркетинг, PR, реклама
- Поиск работы
- Бизнес
- Банковское дело
- Малый бизнес
- Ценные бумаги и инвестиции
- Краткое содержание
- Бухучет и аудит
- Ораторское искусство / риторика
- Корпоративная культура, бизнес
- Финансы
- Государственное и муниципальное управление
- Менеджмент
- Зарубежная деловая литература
- Продажи
- Переговоры
- Личная эффективность
- Торговля
- Научные и научно-популярные книги
- Биофизика
- География
- Экология
- Биохимия
- Рефераты
- Культурология
- Техническая литература
- История
- Психология
- Медицина
- Прочая научная литература
- Юриспруденция
- Биология
- Политика
- Литературоведение
- Религиоведение
- Научпоп
- Психология, личное
- Математика
- Психотерапия
- Социология
- Воспитание детей, педагогика
- Языкознание
- Беременность, ожидание детей
- Транспорт, военная техника
- Детская психология
- Науки: разное
- Педагогика
- Зарубежная психология
- Иностранные языки
- Филология
- Радиотехника
- Деловая литература
- Физика
- Альтернативная медицина
- Химия
- Государство и право
- Обществознание
- Образовательная литература
- Учебники
- Зоология
- Архитектура
- Науки о космосе
- Ботаника
- Астрология
- Ветеринария
- История Европы
- География
- Зарубежная публицистика
- О животных
- Шпаргалки
- Разная литература
- Зарубежная литература о культуре и искусстве
- Пословицы, поговорки
- Боевые искусства
- Прочее
- Периодические издания
- Фанфик
- Военное
- Цитаты из афоризмов
- Гиды, путеводители
- Литература 19 века
- Зарубежная образовательная литература
- Военная история
- Кино
- Современная литература
- Военная техника, оружие
- Культура и искусство
- Музыка, музыканты
- Газеты и журналы
- Современная зарубежная литература
- Визуальные искусства
- Отраслевые издания
- Шахматы
- Недвижимость
- Великолепные истории
- Музыка, танцы
- Авто и ПДД
- Изобразительное искусство, фотография
- Истории из жизни
- Готические новеллы
- Начинающие авторы
- Спецслужбы
- Подростковая литература
- Зарубежная прикладная литература
- Религия и духовность
- Старинная литература
- Справочная литература
- Компьютеры и Интернет
- Блог
Язык программирования C++. Пятое издание - Стенли Липпман
Шрифт:
Интервал:
Закладка:
12.1.1. Класс shared_ptr
Подобно векторам, интеллектуальные указатели являются шаблонами (см. раздел 3.3). Поэтому при создании интеллектуального указателя следует предоставить дополнительную информацию — в данном случае тип, на который способен указывать указатель. Подобно векторам, этот тип указывают в угловых скобках, следующих за именем типа определяемого интеллектуального указателя:
shared_ptr<string> p1; // shared_ptr может указывать на строку
shared_ptr<list<int>> p2; // shared_ptr может указывать на
// список целых чисел
Инициализированный по умолчанию интеллектуальный указатель хранит нулевой указатель (см. раздел 2.3.2). Дополнительные способы инициализации интеллектуального указателя рассматриваются в разделе 12.1.3.
Интеллектуальный указатель используется теми же способами, что и обычный указатель. Обращение к значению интеллектуального указателя возвращает объект, на который он указывает. Когда интеллектуальный указатель используется в условии, результат проверки может засвидетельствовать, не является ли он нулевым:
// если указатель p1 не нулевой и не указывает на пустую строку
if (p1 && p1->empty())
*p1 = "hi"; // обратиться к значению p1, чтобы присвоить ему
// новое значение строки
Список общих функций указателей shared_ptr и unique_ptr приведен в табл. 12.1. Функции, специфические для указателя shared_ptr, перечислены в табл. 12.2.
Таблица 12.1. Функции, общие для указателей shared_ptr и unique_ptr
shared_ptr<T> sp unique_ptr<T> up Нулевой интеллектуальный указатель, способный указывать на объекты типа Т p При использовании указателя p в условии возвращается значение true, если он указывает на объект *p Обращение к значению указателя p возвращает объект, на который он указывает p->mem Синоним для (*p).mem p.get() Возвращает указатель, хранимый указателем p. Используйте его осторожно, поскольку объект, на который он указывает, может прекратить существование после удаления его интеллектуальным указателем swap(p, q) p.swap(q) Обменивает указатели в p и qТаблица 12.2. Функции, специфические для указателя shared_ptr
make_shared<T>(args) Возвращает указатель shared_ptr на динамически созданный объект типа Т. Аргументы args используются для инициализации создаваемого объекта shared_ptr<T> p(q) p — копия shared_ptr q; инкремент счетчика q. Тип содержащегося в q указателя должен быть приводим к типу Т* (см. раздел 4.11.2) p = q p и q — указатели shared_ptr, содержащие указатели, допускающие приведение друг к другу. Происходит декремент счетчика ссылок p и инкремент счетчика q; если счетчик указателя p достиг 0, память его объекта освобождается p.unique() Возвращает true, если p.use_count() равно единице, и значение false в противном случае p.use_count() Возвращает количество объектов, совместно использующих указатель p; может выполняться очень медленно, предназначена прежде всего для отладки Функция make_shared()Наиболее безопасный способ резервирования и использования динамической памяти подразумевает вызов библиотечной функции make_shared(). Она резервирует и инициализирует объект в динамической памяти, возвращая указатель типа shared_ptr на этот объект. Как и типы интеллектуальных указателей, функция make_shared() определена в заголовке memory.
При вызове функции make_shared() следует указать тип создаваемого объекта. Это подобно использованию шаблона класса — за именем функции следует указание типа в угловых скобках:
// указатель shared_ptr на объект типа int со значением 42
shared_ptr<int> p3 = make_shared<int>(42);
// р4 указывает на строку со значением '9999999999'
shared_ptr<string> р4 = make_shared<string>(10, '9');
// р5 указывает на объект типа int со значением по
// умолчанию (p. 3.3.1) 0
shared_ptr<int> р5 = make_shared<int>();
Подобно функции-члену emplace() последовательного контейнера (см. раздел 9.3.1), функция make_shared() использует свои аргументы для создания объекта заданного типа. Например, при вызове функции make_shared<string>() следует передать аргумент (аргументы), соответствующий одному из конструкторов типа string. Вызову функции make_shared<int>() можно передать любое значение, которое можно использовать для инициализации переменной типа int, и т.д. Если не передать аргументы, то объект инициализируется значением по умолчанию (см. раздел 3.3.1).
Для облегчения определения объекта, содержащего результат вызова функции make_shared(), обычно используют ключевое слово auto (см. раздел 2.5.2):
// p6 указывает на динамически созданный пустой вектор vector<string>
auto p6 = make_shared<vector<string>>();
Копирование и присвоение указателей shared_ptrПри копировании и присвоении указателей shared_ptr каждый из них отслеживает количество других указателей shared_ptr на тот же объект:
auto p = make_shared<int>(42); // объект, на который указывает p
// имеет только одного владельца
auto q(p); // p и q указывают на тот же объект
// объект, на который указывают p и q, имеет двух владельцев
С указателем shared_ptr связан счетчик, обычно называемый счетчиком ссылок (reference count). При копировании указателя shared_ptr значение счетчика увеличивается. Например, значение связанного с указателем shared_ptr счетчика увеличивается, когда он используется для инициализации другого указателя shared_ptr, а также при использовании его в качестве правого операнда присвоения, или при передаче его функции (см. раздел 6.2.1), или при возвращении из функции по значению (см. раздел 6.3.2). Значение счетчика увеличивается при присвоении нового значения указателю shared_ptr, а когда он удаляется или когда локальный указатель shared_ptr выходит из области видимости (см. раздел 6.1.1), значение счетчика уменьшается.
Как только счетчик указателя shared_ptr достигает нуля, он автоматически освобождает объект, на который указывает:
auto r = make_shared<int>(42); // объект int, на который указывает r,
// имеет одного владельца
r = q; // присвоение r переводит этот указатель на другой адрес
// приращение счетчика владельцев объекта, на который указывает q
// уменьшение счетчика владельцев объекта, на который указывает r
// объект, на который указывал r, не имеет более владельцев;
// он освобождается автоматически
Здесь резервируется переменная типа int, а ее адрес сохраняется в указателе r. Затем указателю r присваивается новое значение. В данном случае r — единственный указатель типа shared_ptr, указывающий на этот объект. В результате присвоения r = q переменная int автоматически освобождается.
Будет ли использован счетчик или другая структура данных для отслеживания количества указателей на совместно используемый объект, зависит от реализации компилятора. Главное то, что класс отслеживает количество указателей shared_ptr на тот же объект и автоматически освобождает его в подходящий момент.
Указатель shared_ptr автоматически удаляет свои объекты…Когда последний указатель shared_ptr на объект удаляется, его класс автоматически удаляет объект, на который он указывает. Для этого используется другая специальная функция-член — деструктор (destructor), аналогичная конструкторам, которые есть у каждого класса. Подобно тому, как конструктор контролирует инициализацию, деструктор контролирует происходящее при удалении объектов этого типа.

