[БЕЗ_ЗВУКА] Здравствуйте. Меня зовут Алексей Зобнин. И в этом цикле видео я вам расскажу, как написать самостоятельно класс, похожий на std::vector, своими руками. У вас может возникнуть вопрос: зачем нам это делать, когда у вас уже была задача под названием SimpleVector, в которой вы делали примерно то же самое? Давайте попробуем разобраться. Посмотрим на одно из авторских решений задачи про SimpleVector из «Коричневого пояса». Давайте заметим, что в предложенном решении класса SimpleVector вы хранили данные этого вектора просто в динамическом массиве. Настоящий же вектор резервирует сырую память заранее и конструирует в ней элементы только при необходимости. Давайте попробуем проиллюстрировать это с помощью несложного теста. В этом тесте у меня уже заготовлена специальная структура, которая в своем конструкторе копирования и в конструкторе по умолчанию подсчитывает количество созданных объектов. Для этого количества я использую такую статическую переменную, которая сразу инициализируется нулем. Давайте попробуем провести эксперимент как с классом SimpleVector, так и со стандартным вектором. Я сделаю простое действие. Я в отдельном блоке заведу SimpleVector этого типа, положу туда десять элементов со значением по умолчанию. Добавлю еще один элемент. А после этого поинтересуюсь, сколько же объектов типа C у меня было создано при использовании SimpleVector. Чтобы не учитывать тот объект c, который у меня написан в самом верху, давайте я здесь в начале блока обнулю этот счетчик. А теперь я скопирую эти строчки кода и сделаю то же самое со стандартным вектором. Изменю SimpleVector на std::vector. И заменю push_back на то написание, которое принято в стандартной библиотеке. Компилирую свою программу. Запускаю. И мы видим на экране, что SimpleVector породил 30 объектов, в то время как std::vector всего лишь 21. Давайте подумаем, откуда там вообще могло взяться 30 объектов. На самом деле, произошла реаллокация. Сначала у нас был вектор на десять объектов. После этого мы вставили очередной элемент. Памяти для хранения этих объектов не хватало, поэтому пришлось забронировать новую память. И SimpleVector забронировал сразу 20 объектов, для того чтобы сделать реаллокацию. В то время как стандартный вектор — только десять. Поэтому ответ: SimpleVector — это класс, который на самом деле подходит для простых и примитивных типов, для которых не страшно порождать лишние объекты в качестве резерва. Настоящий же вектор так не делает. Он создает объекты в памяти только при необходимости. Но давайте поговорим вообще, что такое сложный объект. Если тип не является примитивным, то есть не сводится к комбинации таких простых типов, как int, char, bool, double, то, вообще говоря, для копирования такого объекта недостаточно просто заполнить биты и байты в памяти. Стандарт требует, чтобы для копирования и создания таких объектов мы вызывали специальные функции, которые называются конструкторами, а для удаления объектов пользовались деструкторами. Наш вектор будет шаблонным, поэтому от шаблонного параметра Т, вообще говоря, надо ожидать самого худшего. Мы, вообще говоря, должны рассчитывать на то, что конструктор и оператор присваивания для этого типа будут дорогими. Можно сказать, что объект рождается в муках. В конструкторе и в операторе присваивания могут происходить исключения. В таком случае объект не считается созданным, и наш вектор должен корректно обрабатывать такие ситуации. Однако мы можем рассчитывать на то, что в деструкторе, а также, как правило, в конструкторе перемещения исключения не происходят. Они не покидают пределов этих функций. Можем считать, что наш тип такой. Давайте подытожим, что же нам потребуется от настоящего вектора. Первое: он должен резервировать объекты в сырой памяти, а не конструировать их сразу. Создавать объекты он должен только при необходимости, а удалять сразу, как они станут ненужными. Кроме того, наш вектор должен корректно обрабатывать те исключения, которые могут возникнуть при создании или копировании объектов. И я добавлю такое очевидное требование, о котором вы наверняка знаете, — вектор должен хранить свои объекты непрерывным куском. Давайте посмотрим, как реализован вектор стандартной библиотеки. Надо понимать, что вектор, как и другие классы стандартной библиотеки, написан на самом обыкновенном C++. И вы можете заглянуть в исходники своей стандартной библиотеки, чтобы посмотреть его код. Правда, этот код читать достаточно тяжело. Я открыл один из файлов, в котором описывается вектор моей стандартной библиотеки. Как видите, тут довольно сложно разобраться. Тут обилие макросов, каких-то проверок. Мы напишем, конечно же, вектор, который будет не настолько сложным, как этот код, но который будет выполнять все эти требования, о которых мы сказали. Давайте подведем итоги. В этом цикле видео мы с вами научимся писать свою реализацию настоящего класса Vector, который будет удовлетворять всем требованиям. Заодно мы с вами изучим несколько новых конструкций языка, которые для этого потребуются.