Я борюсь с правильной ментальной моделью и пониманием std::vector
.
Что я думал, что знал
Когда вы создаете вектор типа T, а затем резервируете N элементов длявектор, компилятор в основном находит и резервирует непрерывный блок памяти размером N * sizeof(T)
байт.Например,
// Initialize a vector of int
std::vector<int> intvec;
// Reserve contigious block of 4 4-byte chunks of memory
intvec.reserve(4); // [ | | | ]
// Filling in the memory chunks has obvious behavior:
intvec.push_back(1); // [1| | | ]
intvec.push_back(2); // [1|2| | ]
Тогда мы можем получить доступ к любому элементу во время произвольного доступа, потому что, если мы запрашиваем k-й элемент вектора, мы просто начинаем с адреса памяти начала вектора, а затем«прыжок» k * sizeof(T)
байт, чтобы добраться до k-го элемента.
Пользовательские объекты
Моя интеллектуальная модель ломается для пользовательских объектов неизвестного / переменного размера.Например,
class Foo {
public:
Foo() = default;
Foo(std::vector<int> vec): _vec{vec} {}
private:
std::vector<int> _vec;
};
int main() {
// Initialize a vector Foo
std::vector<Foo> foovec;
// Reserve contigious block of 4 ?-byte chunks of memory
foovec.reserve(4); // [ | | | ]
// How does memory allocation work since object sizes are unkown?
foovec.emplace_back(std::vector<int> {1,2}); // [{1,2}| | | ]
foovec.emplace_back(std::vector<int> {1,2,3,4,5}); // [{1,2}|{1,2,3,4,5}| | ]
return 0;
}
Поскольку мы не знаем размер каждого экземпляра Foo, как foovec.reserve()
выделяет память?Кроме того, как можно достичь времени произвольного доступа, мы не знаем, как далеко «прыгнуть», чтобы добраться до k-го элемента?