12345678910111213141516171819 |
- В main запустил цикл заполнения (std::push_back() ) std::vector <int>. Памяти, выделенной на вектор
- (конкретно на вектор) независимо от размера ровно 24 байта (что наталкивает на размышления).
- Более того, при добавлении очередного элемента в вектор, происходит увеличение только 9-ого байта.
- С изменением capacity изменяется изменяются 16-ый и 17-ый байты, а адрес нулевого элемента совпадает
- с первыми 8 байтами в обратном порядке (little-endian). Выяснилось, что вектор на самом деле хранит
- всего 3 указателя (собственно, каждый из которых занимает ровно 8 байт). Вопрос заключается в том,
- зачем нужно 3 указателя. Как мы уже выяснили, указатель на первый элемент совпадает с первым из
- наших указателей. Логично было проверить, совпадает ли адрес последнего элемента с одним из оставшихся.
- (Ну то есть мы знаем, что если это было бы так, то их разница была бы равна 4 * vector_size,
- т.к. вектор хранит данные типа int). Как оказалось, второй указатель и говорит нам, где заканчивается вектор.
- А вот третий указатель находится дальше - причём всегда так, что между первым и вторым указателем всегда меньше байт,
- чем между вторым и третьим. Вспомнив о том, как устроено добавление в вектор, а именно случай, когда выделенная
- аллокатором память заканчивается, можно предположить, что в момент, когда вектором выделяется память для последующих
- элементов в размере 4 * C * current_vector_size байтов, где C - "магическая" константа (чтобы добавление в вектор
- работало амортизационно за О(1)), и передвигается 3ий указатель. Иными словами, получается, что 3ий указатель - это
- указатель на конец памяти, которая выделена вектору после расширения.
- Ну и собственно касательно цели задания. Capacity не хранится в векторе (как переменная сама по себе) - просто есть
- указателя. На основании расположения первых двух из них вычисляется capacity, а 3ий, как мы уже выяснили, показывает
- конец аллоцированной памяти.
|