[БЕЗ_ЗВУКА] В предыдущих видео мы познакомились с инвалидацией ссылок. Мы узнали, что вектор инвалидирует ссылки, когда мы делаем push_back в него, дек не инвалидирует ссылки, когда в него push_back не делаем, и когда делаем, тоже не инвалидирует. Что есть помимо ссылок, что может страдать от инвалидации? Во-первых, конечно, указатели, потому что указатели и ссылки — это по сути одно и то же. Просто указатели могут быть не инициализированы и могут как-то двигаться по памяти. То есть указатели тоже будут инвалидизироваться. А что есть помимо указателей? Ещё есть итераторы. Вот давайте посмотрим, будут ли инвалидироваться итераторы вектора и дека. Начнём с вектора. Давайте я создам вектор number, положу в него, скажем, всего лишь одно число. Сохраню итератор на это число, begin от numbers. Сохранил итератор, а теперь сделал что-нибудь страшное, например, вставил много-много чисел в этот вектор. Скажем, может быть и не очень много, давайте 2 000 вставим. numbers.push_back от i. Посмотрим, что же теперь будет лежать по этому итератору. Давайте, во-первых, как только мы его получили, мы выведем, что в нём лежит, с помощью оператора *. И после этой вставки мы выведем, что там будет лежать. Скомпилируем код. На самом деле, результат будет ожидаемым. У вас сначала всё было хорошо, а потом стало всё плохо, потому что итераторы вектора по сути являются указателями. Вы и сами в задаче «Символ-вектор» в качестве итераторов вектора использовали указатели. Почему бы так не делать стандартному вектору, правда же? Так и есть. Соответственно, поскольку указатели на элементы вектора инвалидируются при вставке в него, то и итераторы тоже будут инвалидироваться, тут никаких сюрпризов. А что же будет с деком? Давайте я заменю вектор на дек и запущу тот же самый код. Мы знаем, что указатель проинвалидироваться не должен, итератор, в общем, тоже не пострадал. А именно, мы смогли обратиться к элементу по этому итератору. Но давайте вспоминать, в чём же разница между ссылкой и итератором или даже между указателем и итератором. Имея ссылку, вы можете просто обратиться к этому элементу и всё, больше ничего не можете делать. Имея указатель, вы можете походить по памяти как-то, но указатель ничего не знает о том, как устроен этот контейнер, на элемент которого он указывает, и может уйти куда-то не туда за пределы чанка дека, и так далее, много всего нехорошего наделать. А итератор умнее, итератор помогает итерироваться по контейнеру. Логично же, из названия следует. Соответсвенно, по итератору должно быть можно не только сам элемент достать, но и пройтись по контейнеру или, например, прибавить к итератору число и посмотреть, что же там лежит. Давайте попробуем вот по этому итератору, который мы изначально сохранили. Он указывает на начало, а давайте мы с помощью этого итератора попробуем посмотреть на последний элемент дека. Для этого мы прибавим к нему размер дека минус один, it плюс numbers.size минус один. Прибавим и разминуем. Выведем, соответственно, первый элемент дека с помощью итератора, а также последний — с помощью того же самого итератора. Давайте уже поскорее запустим — посмотрим, что же будет. Итак, ничего хорошего не произошло. Вообще всё упало. Почему? Почему так? Казалось бы, я обращался к элементу по этому итератору, всё было хорошо. А потом я прибавил к нему что-то и всё сломалось. В чём же дело? Дело в том, что я этот итератор получил ещё до того, как в дек добавил много элементов. Этот итератор знает только про устройство старого дека. И когда мы захотели прибавить к этому итератору две тысячи, этот итератор сказал: Ой! Я не могу! Я, вообще-то, появился ещё в тот момент, когда дек ещё имел не этот размер. Дек был гораздо меньше, мы в него подобавляли эти элементы, чанки, может, и остались на месте, но вот эти указатели на чанки как-то поперемещались. Всякое может быть. Соответственно, дек смог спасти указатели и ссылки от инвалидации, а вот итераторы — не смог. И этот в целом логично, если просто знать о том, что итераторы мощнее, чем указатели. Итераторы содержат какую-то дополнительную логику, помогающую итерироваться по контейнеру, дополнительную логику, которая помогает прибавить к итератору число и прямо пройтись по контейнеру, как бы сложно он не был устроен. Конечно, некоторые контейнеры сдаются и не позволяют прибавлять числа к своим итераторам, как, например, множества. Но итераторы дека должны уметь такое делать. И если вы добавляете элементы в дек, то указатели ссылки у вас останутся в порядке, валидными, а вот итераторы могут инвалидироваться, что мы и увидели в нашем примере. К слову, раз уж мы узнали о таком интересном свойстве дека, давайте узнаем, что об этом думает документация. Откроем cppreference.com, откроем документацию по методу push_back у дека и сразу же увидим там, что все итераторы, включая итератор за концом, инвалидируются, но ссылки при этом не инвалидируются. То есть, действительно, дек смогу уберечь ссылки от инвалидации, но не смог уберечь от инвалидации итераторы.