我是C++新手,我在我的项目中使用向量类。我发现它非常有用,因为我可以有一个数组,它可以在需要的时候自动重新分配(例如,如果我想要push_back一个项,并且这个向量已经达到了它的最大容量,它会重新分配自己的内存空间给操作系统),所以访问向量的一个元素非常快(它不像一个列表,为了到达"n“元素,我必须遍历”n“第一个元素)。
我发现这个问题非常有用,因为当我想在堆/堆栈中存储我的向量时,他们的回答完美地解释了“内存分配器”是如何工作的:
[1] vector<Type> vect;
[2] vector<Type> *vect = new vector<Type>;
[3] vector<Type*> vect;
然而,一个疑问困扰了我一段时间,我找不到它的答案:每当我构造一个向量并开始将大量的项目推入,它就会达到一个向量满的时刻,因此要继续增长,它需要重新分配,复制到一个新的位置,然后继续pushing_back项(很明显,这种重新分配-它隐藏在类的实现中,所以对我来说是完全透明的)
好吧,如果我已经在堆2上创建了向量,我就不难想象会发生什么:类向量调用malloc,获取新空间,然后将自己复制到新内存中,最后删除调用空闲的旧内存。
然而,当我在堆栈1上构造一个向量时,面纱掩盖了正在发生的事情:当向量必须重新分配时会发生什么?AFAIK,每当在C/C++上输入一个新函数时,计算机就会查看变量的声明,然后展开堆栈以获得放置这些变量所需的空间,但是当函数已经运行时,不能在堆栈上分配更多的空间。类向量是如何解决这个问题的?
发布于 2013-06-25 16:17:23
你写的
..。复制到一个新的位置..。
这不是向量的工作方式。向量数据被复制到一个新位置,而不是向量本身。
我的回答应该给你一个向量是如何设计的概念。
常见的std::向量布局*
注意:实际上,std::allocator
std::vector
很可能是一个空类,而std::vector
可能不会包含这个类的一个实例。对于任意的分配器来说,这可能不是真的。。
在大多数实现中,它由三个指针组成,其中
begin
指向堆上向量的数据内存的开始(如果不是nullptr
,总是在堆上)end
将一个内存位置指向向量数据-> size() == end-begin
的最后一个元素。capacity
点超过向量内存-> capacity() == capacity-begin
的最后一个元素堆栈上的向量
我们声明一个类型为std::vector<T,A>
的变量,其中T
是任意类型,A
是T
(即std::allocator<T>
)的分配器类型。
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
while size() == end-begin == 1
发布于 2013-06-25 14:27:02
向量对象很可能是在堆栈上激发的,但是向量中的数据将在堆上。
(平凡类class foo {int* data;};
具有这个特性)
发布于 2013-06-25 14:28:06
构建向量(堆栈或堆)的方式与此无关。
请参阅std::vector
的文档
在内部,向量使用动态分配的数组来存储它们的元素。当插入新元素时,可能需要重新分配这个数组,以增加大小,这意味着分配一个新数组并将所有元素移动到它。
当向量“增长”时,向量对象不会增长,只有内部动态数组发生变化。
至于它的实现,你可以看看GCC的向量实现。
为了保持简单,它将向量声明为有一个受保护的成员类,类型为_Vector_impl
。
如您所见,它被声明为包含三个指针的结构:
https://stackoverflow.com/questions/17299951
复制相似问题