我读到 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 杰作):
您在堆栈上的 std::vector
实例是一个小对象,其中包含一个指向堆分配缓冲区的指针,以及一些额外的变量来跟踪缓冲区的大小和容量 vector 。
So it seems as though when I
push_back()
to thenumbers
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/