在内部,矢量矢量如何扩展? C ++

时间:2017-02-08 00:08:29

标签: c++ multidimensional-array vector stdvector

假设我有一个这样的程序:

#include<vector>

int main()
{
    std::vector< std::vector < int > > vexample(2);
    vexample[1].push_back(0);
    vexample[0].push_back(0);
}

在第一行,我初始化一个包含2个零长度向量的int的向量。在第二行,我将一个int push_back()放到第二个向量中,导致vexample [1]调整大小。

当第一个vexample [0]由​​于pushback()调整大小时,下一行的矢量矢量会发生什么变化? vexample [2]向前移动了4个字节吗?

2 个答案:

答案 0 :(得分:2)

每个向量都包含一个指向免费存储分配的内存的指针,用于保存其项目。所以vexample没有任何事情发生。 vexample[0]可能重置其指针的数据vexample[1]保持原样,直到您更改IT为止。 vexample个元素都不会变大或变小。

答案 1 :(得分:2)

我认为你对矢量在内部的运作方式存在误解。

向量通常在内部只存储3个东西(即在堆栈上):

  • 大小
  • 其容量(即,无需调整大小即可增长的最大大小)
  • 指向堆上存储实际数据的数组的指针

(通常,出于性能原因,实现使用3个指针,但从概念上讲它是相同的。)

这意味着可以增长或缩小的部分存储在堆上。如果将push_back元素放入vexample[1],您将使其增长,因此大小,容量和指针的值将根据需要进行更新,但这并不意味着它们需要更多空间stack:它仍然是3个固定大小的变量,其中“fixed”表示它是在编译时确定的。

如果我们假设sizecapacity被实现为int并且每个需要4个字节,并且指针需要8个字节,那么你需要一个向量需要4 + 4 + 8 =堆栈上的16个字节,无论它包含的元素的类型和数量,以及堆上的capacity * sizeof(T)个字节。堆上使用的内存量可能不同,而堆栈上的内存不能。

在您的情况下,vexample的元素也是向量,因此每个元素需要16个字节,加上分配容量的大小。所以,内存布局是这样的:

vexample在堆栈上占用16个字节。在这16个字节中,8个是指向堆区域的指针,其中有2个元素的数组,每个元素需要16个字节,因此它是一个32字节的连续块:前16个用于vexample[0],最后16个是vexample[1]。它们中的每一个都包含一个指向int数组的指针。

当这些向量中的任何一个增长时,堆上的数据可能需要重新分配,但这并不会“推开”其他任何东西,因为虽然确实必须连续存储相同向量的元素,对应于不同向量的存储区域没有这样的要求。因此,当您将push_back元素加入vexample[1]并强制它成长时,vexample[0]vexamplevexample[2](如果存在)都不需要做任何事情。特别是,vexample[2]不需要移动,因为vexample[1]增长:相反,如果vexample[1]增长,那么vexample[1]必须为自己找到一个新的位置。

如果向量的可变大小部分保存在堆栈中,并且所有内容彼此相邻存储,则所有这些都将成为问题。但这正是你只存储一个指向堆的指针的原因,并且所有增长和收缩都发生在那里,它不会造成任何伤害。