c++ - std::vector 在内存中是什么样的?

标签 c++ memory vector contiguous

我读到 std::vector 应该是连续的。我的理解是,它的元素应该存储在一起,而不是分散在内存中。我只是简单地接受了这一事实,并在使用它的 data() 方法来获取底层连续内存时使用了这一知识。

但是,我遇到了一种情况, vector 的内存以一种奇怪的方式表现:

std::vector<int> numbers;
std::vector<int*> ptr_numbers;
for (int i = 0; i < 8; i++) {
    numbers.push_back(i);
    ptr_numbers.push_back(&numbers.back());
}

我希望这会给我一个包含一些数字的 vector 和一个指向这些数字的指针 vector 。但是,当列出 ptr_numbers 指针的内容时,会有不同的看似随机的数字,就好像我访问了错误的内存部分。

我每一步都试过检查内容:

for (int i = 0; i < 8; i++) {
    numbers.push_back(i);
    ptr_numbers.push_back(&numbers.back());
    for (auto ptr_number : ptr_numbers)
       std::cout << *ptr_number << std::endl;
    std::cout << std::endl;
}

结果大致如下:

1

some random number
2

some random number
some random number
3

所以当我 push_back()numbers vector 时,它的旧元素似乎改变了它们的位置。

那么,std::vector 是一个连续的容器究竟是什么意思,为什么它的元素会移动呢?它是否可能将它们存储在一起,但在需要更多空间时将它们一起移动?

编辑:std::vector 是否仅从 C++17 开始连续? (只是为了让对我之前声明的评论与 future 的读者相关。)

最佳答案

大致是这样的(请原谅我的 MS Paint 杰作):

vector memory layout

您在堆栈上的 std::vector 实例是一个小对象,其中包含一个指向堆分配缓冲区的指针,以及一些额外的变量来跟踪缓冲区的大小和容量 vector 。


So it seems as though when I push_back() to the numbers vector, its older elements change their location.

堆分配的缓冲区具有固定容量。当你到达缓冲区的末尾时,一个新缓冲区将被分配到堆上的其他地方,所有之前的元素都将被移动到新的缓冲区中。他们的地址因此会改变。


Does it maybe store them together, but moves them all together, when more space is needed?

大概,是的。 std::vector 仅当不发生重新分配时,才能保证元素的迭代器和地址稳定性。


I am aware, that std::vector is a contiguous container only since C++17

std::vector 的内存布局自其首次出现在标准中以来没有改变。 ContiguousContainer只是在编译时添加的一个“概念”,用于区分连续容器与其他容器。

关于c++ - std::vector 在内存中是什么样的?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52330010/

相关文章:

python - 从 scikit 创建 ngrams 学习和计数向量化器抛出内存错误

c++ - vector 的两个特征之间的差异

C++ const 引用 vector(或其他动态容器)中的类变量

c++ - 如何在 gcc 中链接到我自己的库?

c# - WinCE 中的屏幕校准

c++ - 读入没有空终止符空间的数组是否合法?

javascript - 释放 ThreeJS 应用程序的内存

java - Java中ArrayList的内存大小是多少

c++ - 带有索引和迭代器的 vector

c++ - 在多态对象上使用 typeid 时,必须定义它吗?