- Фантастика и фэнтези
- Ироническое фэнтези
- Стимпанк
- Детективная фантастика
- Киберпанк
- Попаданцы
- LitRPG
- Космоопера
- Технофэнтези
- Городская фантастика
- Русское фэнтези
- Юмористическая фантастика
- Космическая фантастика
- Боевое фэнтези
- Эпическая фантастика
- Зарубежная фантастика
- Книги магов
- Мистика
- Разная фантастика
- Разное фэнтези
- Любовное фэнтези
- Романтическая фантастика
- Городское фентези
- Историческая фантастика
- Историческое фэнтези
- Социально-философская фантастика
- Сказочная фантастика
- Иностранное фэнтези
- Романтическое фэнтези
- Ироническая фантастика
- Ужасы и Мистика
- Постапокалипсис
- Героическая фантастика
- Фэнтези
- Научная Фантастика
- Социально-психологическая
- Альтернативная история
- Боевая фантастика
- Разная литература
- Пословицы, поговорки
- Шахматы
- Визуальные искусства
- Фанфик
- Авто и ПДД
- Военное
- Отраслевые издания
- Гиды, путеводители
- Зарубежная образовательная литература
- Военная история
- Цитаты из афоризмов
- Современная литература
- Великолепные истории
- Начинающие авторы
- Современная зарубежная литература
- Боевые искусства
- Изобразительное искусство, фотография
- Кино
- Литература 19 века
- Недвижимость
- Музыка, музыканты
- Готические новеллы
- Истории из жизни
- Культура и искусство
- Спецслужбы
- Зарубежная прикладная литература
- Музыка, танцы
- Подростковая литература
- Прочее
- Военная техника, оружие
- Газеты и журналы
- Периодические издания
- Домоводство, Дом и семья
- Любовные романы
- Экономическая литература
- Научные и научно-популярные книги
- О животных
- Биохимия
- Культурология
- Юриспруденция
- Политика
- Психотерапия
- Языкознание
- Научпоп
- Медицина
- Психология, личное
- Радиотехника
- Филология
- Педагогика
- Образовательная литература
- Деловая литература
- Физика
- Науки: разное
- Химия
- Воспитание детей, педагогика
- Детская психология
- Зарубежная публицистика
- Биология
- Архитектура
- Зарубежная психология
- Науки о космосе
- Социология
- Математика
- География
- Беременность, ожидание детей
- Литературоведение
- Транспорт, военная техника
- Обществознание
- Зоология
- География
- Альтернативная медицина
- Иностранные языки
- Ветеринария
- Рефераты
- Астрология
- Биофизика
- Экология
- История Европы
- Учебники
- Шпаргалки
- Государство и право
- Ботаника
- Религиоведение
- История
- Техническая литература
- Прочая научная литература
- Психология
- Детективы и Триллеры
- Справочная литература
- Проза
- Новелла
- Юмор
- Проза
- Историческая проза
- Русская современная проза
- Советская классическая проза
- Повести
- Очерки
- Эссе
- Рассказы
- Зарубежная современная проза
- Сентиментальная проза
- Зарубежная классика
- Афоризмы
- Эпистолярная проза
- Феерия
- Семейный роман/Семейная сага
- Разное
- Антисоветская литература
- Магический реализм
- Русская классическая проза
- Современная проза
- О войне
- Контркультура
- Классическая проза
- Поэзия, Драматургия
- Детская литература
- Детская фантастика
- Детские остросюжетные
- Детские стихи
- Детские приключения
- Внеклассное чтение
- Учебная литература
- Зарубежные детские книги
- Бизнес
- Загадки
- Книги для подростков
- Школьные учебники
- Детский фольклор
- Книги для дошкольников
- Детские детективы
- Детская познавательная и развивающая литература
- Буквари
- Прочая детская литература
- Сказка
- Детская проза
- Детская образовательная литература
- Юмор
- Документальные книги
- Бизнес
- Внешнеэкономическая деятельность
- Тайм-менеджмент
- Кадровый менеджмент
- О бизнесе популярно
- Управление, подбор персонала
- Бизнес
- Менеджмент и кадры
- Продажи
- Экономика
- Ценные бумаги и инвестиции
- Малый бизнес
- Делопроизводство, офис
- Корпоративная культура, бизнес
- Банковское дело
- Финансы
- Зарубежная деловая литература
- Ораторское искусство / риторика
- Личные финансы
- Интернет-бизнес
- Поиск работы
- Государственное и муниципальное управление
- Бухучет и аудит
- Работа с клиентами
- Менеджмент
- Краткое содержание
- Личная эффективность
- Переговоры
- Приключения
- Старинная литература
- Религия и духовность
- Компьютеры и Интернет
- Блог
Читаем без скачивания C++17 STL Стандартная библиотека шаблонов - Яцек Галовиц
Шрифт:
Интервал:
Закладка:
struct person {
string name;
size_t age;
person(string n, size_t a)
: name{move(n)}, age{a}
{ cout << "CTOR " << name << 'n'; }
~person() { cout << "DTOR " << name << 'n'; }
};
3. Определим общие указатели, которые имеют корректные типы, чтобы указывать на переменные-члены name и age экземпляра класса person:
int main()
{
shared_ptr<string> shared_name;
shared_ptr<size_t> shared_age;
4. Далее войдем в новую область видимости, создадим объект типа person и позволим общему указателю управлять им:
{
auto sperson (make_shared<person>("John Doe", 30));
5. Затем позволим первым двум общим указателям указывать на его члены name и age. Прием, который мы задействуем, заключается в использовании конкретного конструктора типа shared_ptr, который принимает общий указатель и указатель на член общего объекта. Таким образом можно управлять объектом, не указывая на него самого!
shared_name = shared_ptr<string>(sperson, &sperson->name);
shared_age = shared_ptr<size_t>(sperson, &sperson->age);
}
6. После выхода из области видимости выведем на экран значения переменных name и age. Это возможно только в том случае, если память для объекта все еще выделена.
cout << "name: " << *shared_name
<< "nage: " << *shared_age << 'n';
}
7. Компиляция и запуск программы дадут следующий результат. Из сообщения деструктора мы видим, что объект все еще жив и память для него выделена, когда мы получаем доступ к значениям переменных name и age с помощью указателей на члены!
$ ./shared_members
CTOR John Doe
name: John Doe
age: 30
DTOR John Doe
Как это работает
В этом разделе мы сначала создали общий указатель, управляющий объектом person, память для которого выделяется динамически. Затем создали два других умных указателя, указывающих на объект типа person, но не на сам объект, а на его члены name и age.
Чтобы подытожить созданный сценарий, взглянем на рис. 8.4.
Обратите внимание: shared_ptr1 указывает на сам объект person, а shared_name и shared_age — на члены name и age того же объекта. По всей видимости, они будут управлять всем жизненным циклом объекта. Это возможно потому, что указатели внутреннего блока управления все еще ссылаются на тот же блок управления, независимо от того, на какой подобъект указывают отдельные общие указатели.
В этом сценарии счетчик использования блока управления равен 3. Таким образом, объект типа person не будет удален при уничтожении shared_ptr1, поскольку другие общие указатели все еще владеют объектом.
При создании подобных экземпляров общих указателей, указывающих на члены общего объекта, синтаксис выглядит несколько странно. Чтобы получить экземпляр типа shared_ptr<string>, который указывает на член name общего экземпляра типа person, нужно написать следующий код:
auto sperson (make_shared<person>("John Doe", 30));
auto sname (shared_ptr<string>(sperson, &sperson->name));
Чтобы получить указатель на конкретный член общего объекта, мы создаем экземпляр общего указателя, чей тип специализирован для того члена, к которому нужно получить доступ. Именно поэтому используем конструкцию shared_ptr<string>. Затем в конструкторе сначала предоставляем оригинальный общий указатель, сопровождающий объект типа person, а в качестве второго аргумента — адрес объекта, которым будет пользоваться новый общий указатель при разыменовании.
Генерируем случайные числа и выбираем правильный генератор случайных чисел
Чтобы получить случайные числа, программисты С++ до появления С++11 обычно просто использовали функцию rand() из библиотеки C. Начиная с C++11, в нашем распоряжении целый арсенал генераторов случайных чисел, они служат для разных целей и имеют различные характеристики.
Эти генераторы не говорят сами за себя, так что в данном разделе рассмотрим их все. Мы увидим, чем они отличаются, научимся выбирать правильный и узнаем, что, скорее всего, никогда не будем ими пользоваться.
Как это делается
В этом примере мы реализуем процедуру, которая выводит на экран гистограмму, содержащую числа, создаваемые генератором случайных чисел. Затем запустим все генераторы случайных чисел, доступные в STL, и воспользуемся нашей процедурой, чтобы исследовать результаты. Данная программа содержит множество повторяющихся фрагментов, поэтому может быть полезным просто скопировать исходный код из репозитория, дополняющего эту книгу, а не писать повторяющийся код вручную.
1. Сначала включим все заголовочные файлы, а затем объявим об использовании пространства имен std по умолчанию:
#include <iostream>
#include <string>
#include <vector>
#include <random>
#include <iomanip>
#include <limits>
#include <cstdlib>
#include <algorithm>
using namespace std;
2. Затем реализуем вспомогательную функцию, которая позволит сопровождать и выводить на экран статистику для каждого типа генераторов случайных чисел. Она принимает два параметра — количество сегментов и количество образцов. Мы сразу увидим, для чего они нужны. Тип генератора случайных чисел определяется с помощью шаблонного параметра RD. Первое, что мы сделаем в этой функции, — определим псевдоним типа для полученного численного типа чисел, возвращаемых генератором. Кроме того, убедимся, что у нас есть как минимум десять сегментов:
template <typename RD>
void histogram(size_t partitions, size_t samples)
{
using rand_t = typename RD::result_type;
partitions = max<size_t>(partitions, 10);
3. Далее создадим экземпляр генератора типа RD. Затем определим переменную-делитель с именем div. Все генераторы случайных чисел создают случайные числа в диапазоне от 0 до RD::max(). Аргумент функции partitions позволяет вызывающей стороне выбирать, на сколько сегментов мы разделим каждый диапазон случайных чисел. Разделив наибольшее возможное значение на количество сегментов, мы узнаем, насколько большим является каждый из них:
RD rd;
rand_t div ((double(RD::max()) + 1) / partitions);
4. Создадим вектор переменных-счетчиков. Он будет иметь размер, равный количеству сегментов. Затем получим случайные значения от генератора в количестве, равном значению переменной samples. Выражение rd() получает случайное число от генератора и изменяет его внутреннее состояние так, чтобы подготовить его к выдаче следующего случайного числа. Разделив каждое случайное число на div, мы получим номер сегмента, в который оно попадает, и можем увеличить соответствующий