你写的
[...] 将自身复制到新位置 [...]
[...] copy itself to a new location [...]
这不是矢量的工作方式.矢量数据将复制到新位置,而不是矢量本身.
我的回答应该让您了解矢量的设计方式.
注意:std::allocator 实际上可能是一个空类,std::vector 可能不包含此类的实例.对于任意分配器,情况可能并非如此.
在大多数实现中,它由三个指针组成,其中
- begin 指向vector在堆上的数据内存的开始(如果不是nullptr,则一直在堆上)
- end 指向向量数据最后一个元素之后的一个内存位置-> size() == end-begin
- capacity 指向超过向量内存最后一个元素的内存位置 -> capacity() == capacity-begin
- begin points to the start of the data memory of the vector on the heap (always on the heap if not nullptr)
- end points one memory location past the last element of the vector data
-> size() == end-begin
- capacity points on memory location past the last element of the vector memory -> capacity() == capacity-begin
我们声明一个 std::vector 类型的变量,其中 T 是任何类型,A 是分配器类型对于 T(即 std::allocator).
std::vector<T, A> vect1;
这在内存中看起来如何?
如我们所见:堆上什么都没有发生,但变量占用了堆栈上所有成员所需的内存.它就在那里,它会一直留在那里直到 vect1 超出范围,因为 vect1 只是一个对象,就像任何其他 double 类型的对象一样,int 或其他什么.无论它在堆上处理多少内存,它都会坐在它的堆栈位置上并等待被销毁.
vect1 的指针不指向任何地方,因为向量是空的.
现在我们需要一个指向向量的指针,并使用一些动态堆分配来创建向量.
std::vector<T, A> * vp = new std::vector<T, A>;
我们再来看看内存.
我们的 vp 变量在堆栈上,我们的向量现在在堆上.同样,向量本身不会在堆上移动,因为它的大小是恒定的.如果发生重新分配,只有指针(begin、end、capacity)将移动到内存中的数据位置之后.让我们看看那个.
现在我们可以开始将元素推送到向量.让我们看看vect1.
T a;
vect1.push_back(a);
变量 vect1 仍然在原来的位置,但堆上的内存被分配为包含 T 的一个元素.
如果我们再添加一个元素会发生什么?
vect1.push_back(a);
- 在堆上为数据元素分配的空间将不够(因为它只有一个内存位置).
- 将为两个元素分配一个新的内存块
- 第一个元素将被复制/移动到新存储.
- 旧内存将被释放.
我们看到:新的内存位置不同了.
为了有更多的了解,让我们看看我们销毁最后一个元素时的情况.
vect1.pop_back();
分配的内存不会改变,但最后一个元素将调用其析构函数,并且结束指针向下移动一个位置.
如您所见:capacity() == capacity-begin == 2 而 size() == end-begin == 1
这篇关于c++ Vector,每当它在堆栈上扩展/重新分配时会发生什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持前端之家!
本文链接:https://www.f2er.com/3186435.html