2

当一个或多个元素改变大小时,向量会发生什么?

详细说明,

#include <string>
#include <vector>
using namespace std;
int main() {
    vector<string> v;
    v.push_back("first string");
    v.push_back("2nd string");
    v[0] += " has increased in size";
}

“v[0] += ...”会发生什么?是否会进行大规模重新分配,以保持字符串和向量中的内存连续?

4

4 回答 4

6

中不会有内存重新分配,vector几乎可以肯定会重新分配string,尽管标准没有说明这一点。字符串就像一个向量,因为它将内容与字符串对象本身分开。

于 2012-09-11T04:05:15.113 回答
5

No.string将其实际字符串数据存储在单独分配的内存中(模短字符串优化)。对象的实际大小永远不会改变,并且在编译时是固定的。任何此类动态调整大小都是使用单独分配的内存或对象层次结构来完成的(例如,set/map 使用节点树,list 使用节点的双链表等)。

于 2012-09-11T04:04:47.560 回答
1

是否会进行大规模重新分配,以保持字符串和向量中的内存连续?

向量的元素是连续的,但在每个包含的字符串中都有一个指向动态分配存储的指针,其中存储了文本内容(假设字符串不是空的,也不是短到足以放入固定大小的内部缓冲区 - 一种已知的技术作为“短字符串优化”,实现可能但不需要使用)。

现在,对于向量和字符串,重要的是要了解当前大小(元素数量/char数据)和容量(已经保留的堆数量以及容器可以增长而无需分配的堆数量)之间的差异一个新的堆区域并移动元素。

因此,如果现有容量足够,则字符串连接就位。如果容量必须增加,则该字符串指向动态内存的指针被更新以寻址新分配的更大堆区域,文本内容被复制到其中,然后释放原始堆区域。

这些push_back()操作可能会导致向量重新分配,但字符串对象“拥有”单独的堆内存块。

如果你想知道你的具体实现在做什么,你可以打印出你的容器size()capacity()操作之前和之后,以及第一个元素的地址......不过,容量超过大小之后的数量标准未指定重新分配,因此甚至可能随编译器标志/版本、操作系统等而改变。

从图表上看,像这样:

VECTOR:                /-------->[first string's text]...extra capacity...
[ first string object /]
[    second string object   \]
...extra vector capacity...  \-->[second string's text]...extra capacity...
于 2012-09-11T04:38:13.220 回答
0

string对象是固定大小的。如果包含的字符串不适合字符串实现提供的内部存储(如果有),则单独分配。它与任何其他字符串存储都不连续,至少不是故意的。

于 2012-09-11T04:30:42.173 回答