В 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 не хранится в векторе (как переменная сама по себе) - просто есть 3 указателя. На основании расположения первых двух из них вычисляется capacity, а 3ий, как мы уже выяснили, показывает конец аллоцированной памяти.