当向量需要更多内存并分配内存时,指针会发生啥?

Posted

技术标签:

【中文标题】当向量需要更多内存并分配内存时,指针会发生啥?【英文标题】:What happen to pointers when vectors need more memory and realocate memory?当向量需要更多内存并分配内存时,指针会发生什么? 【发布时间】:2011-11-24 18:01:40 【问题描述】:

当向量需要更多内存时,它会在某个地方重新分配内存,我还不知道在哪里!然后指针变得无效,对此有什么好的解释吗?

我的意思是他们去了哪里,我的容器会发生什么? (不是链表的)

【问题讨论】:

一些代码来证明这一点会很有用... 我认为这可能是个问题:std::vector<int> foo(10); int *ip = &foo.front();。重新分配可能会使*ip 失效,对吧?但是,您不应该以这种方式滥用 std::vector。使用迭代器。 Protip:使用索引而不是指针。 @zerm 重新分配也会使迭代器无效。顺便说一句,它不会使*ip失效,当然只会使ip失效。 @ChristianRau 是的,对不起,你在这两个方面都是绝对正确的。 【参考方案1】:

简答:一切都会好起来的。不用担心这个,继续工作吧。

中等答案:向向量添加元素或从向量中删除元素会使所有迭代器和引用/指针无效(可能除了从后面删除)。就那么简单。不要引用任何旧的迭代器并在这样的操作之后获取新的迭代器。示例:

std::vector<int> v = get_vector();

int & a = v[6];
int * b = &v[7];
std::vector<int>::iterator c = v.begin();
std::advance(it, 8);

v.resize(100);

现在abc 都无效:您不能使用 a,也不能取消引用 b 或@987654328 @。

长答案:向量跟踪动态内存。当内存耗尽时,它会在别处分配一个新的、更大的块并复制(或移动)所有旧元素(然后释放旧内存,销毁旧对象)。内存分配和释放由allocator(通常是std::allocator&lt;T&gt;)完成,它通常又调用::operator new() 来获取内存,而后者通常又调用malloc()。详细信息可能会有所不同,具体取决于您的平台。在任何情况下,任何以前持有的引用、指针或迭代器都不再有效(可能是因为它们引用了现在已释放的内存,尽管标准中没有说明为什么它们是无效的)。

【讨论】:

但是……“一切都会好起来的”是什么意思?我认为 OP 考虑使用指针,指向矢量数据?我认为只有他放弃这个想法,一切都会好起来的。 我认为您没有回答实际问题,这是关于矢量数据的指针,在重新分配之前获取。 好吧,我仍然同意反对者(我认为 Macmade 是)的观点,即您应该提到指针会发生什么。或者至少有这样的问题,我宁愿避免说一切都会好起来的。我的意思是,简短的回答是唯一引起关注的部分。 我仍然觉得“一切都会好起来的”有点误导。 :X 我认为在“我有指向向量元素的指针”的上下文中,“没关系”不太好。 从C的角度看一下这个:gist.github.com/1392643当然不行,这样写代码很危险。但我认为 OP 对向量的使用感到困惑,实际上是在询问这种代码在使用向量时是否可以......【参考方案2】:

当您在vector 中添加或删除项目时,指向其中项目的所有迭代器(和指针)都将失效。如果您需要在向量中存储指向某项的指针,则将向量设为const,或使用其他容器。

vector 存储东西的位置对您来说并不重要。你不需要做任何事情,让它完成它的工作。

【讨论】:

【参考方案3】:

当您使用std::vector 时,该类会处理有关内存分配、指针、调整大小等所有细节。

vector 类通过迭代器和引用公开其内容。向量的突变可能会使迭代器和引用失效,因为可能需要重新分配。

使用指针访问内容是有效的,因为vector 类保证将其元素存储在连续的内存位置。显然,由于潜在的重新分配,列表的任何突变都可能使指向其内容的任何指针无效。因此,如果你曾经使用指针访问一个元素,那么一旦你改变了向量,你就必须认为这些指针是无效的。简而言之,同样的规则适用于指向内容的指针,也适用于引用。

如果您想维护对向量中某个项目的引用,并且即使在突变后该引用仍然有效,那么您应该记住索引而不是指针或对该项目的引用。在这种情况下,添加到向量的末尾是完全安全的,并且您的索引值仍然指向同一个元素。

【讨论】:

您可以使用 &vect[0] 访问内部指针...不建议但很有可能。 我有时使用&amp;vect.front():例如将 OpenGL 顶点存储在 std::vector&lt;float&gt; 中并使用它。但是,最终某些 OpenGL 函数需要float*,所以只需传递&amp;vect.front() @David 我的意思是你确实有访问权限,尽管这个答案声称。 @WillBickford 仅当您滥用参考文献时。 @David 大多数时候,您唯一需要知道的是数据是连续存储的(即使您并不总是必须知道),这是您始终知道的事实(假设您知道您正在使用标准 C++)。当标准保证其行为时,我绝对不会称之为滥用。制作指向引用的指针有什么不好的,这绝不是滥用。

以上是关于当向量需要更多内存并分配内存时,指针会发生啥?的主要内容,如果未能解决你的问题,请参考以下文章

当我取消引用指针并将值分配给某个变量时,内存会发生啥?

C alloca 函数 - 当试图分配太多内存时会发生啥

当试图释放堆管理器分配的内存时会发生啥,它分配的比要求的多?

程序员最容易出现啥问题

C - free() 之后内存会发生啥? [复制]

当您动态分配内存时,“指针类型”有啥意义?