当一个或多个元素的大小发生变化时,矢量会发生什么?
详细说明,
#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";
}
&#34; v [0] + = ...&#34 ;?会发生什么?是否会进行质量重新分配,以保持字符串和向量中的内存连续?
答案 0 :(得分:6)
vector
中没有内存重新分配,而string
几乎肯定会有重新分配,尽管标准没有说明这一点。字符串就像一个向量,它将内容与字符串对象本身分开。
答案 1 :(得分:5)
没有。 string
将其实际字符串数据存储在单独分配的内存中(模数短字符串优化)。对象的实际大小永远不会改变,并且在编译时是固定的。任何这样的动态大小调整都是使用单独分配的内存或对象的层次结构来完成的(例如,set / map使用节点树,list使用双链节点列表等)。
答案 2 :(得分: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...
答案 3 :(得分:0)
string
对象是固定大小。如果包含的字符串不适合字符串实现提供的内部存储(如果有),则会单独分配。它与任何其他字符串存储不相邻,至少不是故意的。