std::array、std::vector和原始数组的大小

Size of std::array, std::vector and raw array

本文关键字:std 数组 array vector 原始      更新时间:2023-10-16

让我们有,

std::array <int,5> STDarr;
std::vector <int> VEC(5);
int RAWarr[5];

我试着把它们的尺寸弄成

std::cout << sizeof(STDarr) + sizeof(int) * STDarr.max_size() << std::endl;
std::cout << sizeof(VEC) + sizeof(int) * VEC.capacity() << std::endl;
std::cout << sizeof(RAWarr) << std::endl;

输出为,

40
20
40

这些计算正确吗?考虑到我没有足够的内存用于std::vector,并且无法逃脱动态分配,我应该使用什么?如果我知道std::array会降低内存需求,我可以更改程序使数组变为静态。

这些数字是错误的。此外,我也不认为它们代表了你认为它们代表的东西。让我解释一下。

首先是关于他们错了的部分。不幸的是,你没有显示sizeof(int)的值,所以我们必须推导它。在你使用的系统上,int的大小可以计算为

size_t sizeof_int = sizeof(RAWarr) / 5; // => sizeof(int) == 8

因为这本质上是sizeof(T)的定义:它是数组中T类型的两个相邻对象的开头之间的字节数。这恰好与STDarr的数字打印不一致:类模板std::array<T, n>被指定为嵌入类型为Tn对象数组。此外,std::array<T, n>::max_size()是一个产生n的常量表达式。也就是说,我们有:

40                                               // is identical to
sizeof(STDarr) + sizeof(int) * STDarr.max_size() // is bigger or equal to
sizeof(RAWarr) + sizeof_int * 5                  // is identical to
40             + 40                              // is identical to
80

这就是40 >= 80——一个反证。

类似地,第二次计算也与第三次计算不一致:std::vector<int>至少包含5元素,并且capacity()必须大于size()。此外,std::vector<int>的大小是非零的。也就是说,以下内容必须始终正确:

sizeof(RAWarr) < sizeof(VEC) + sizeof(int) * VEC.capacity()

无论如何,所有这些都与您的实际问题无关:使用Tstd::array<T, n>std::vector<T>的内置数组表示T类型的n对象的开销是多少?这个问题的答案是:

  1. 内置阵列T[n]使用sizeof(T) * n
  2. CCD_ 26使用与CCD_ 27相同的大小
  3. std::vector<T>(n)需要一些控制数据(大小、容量,可能还有分配器)加上至少'n*sizeof(T)'字节来表示其实际数据。它也可以选择具有比CCD_ 30大的CCD_

除了这些数字之外,实际使用这些数据结构中的任何一个都可能需要额外的内存:

  1. 所有对象都在适当的地址对齐。为此,对象前面可能有额外的字节
  2. 当对象被分配到堆上时,除了可用的内存之外,内存管理系统还会包括几个字节。这可能只是一个关于大小的词,但它可能是分配机制想要的任何东西。此外,该内存可能存在于分配内存之外的其他地方,例如某个地方的哈希表中

好吧,我希望这能提供一些见解。然而,这里出现了重要的消息:如果std::vector<T>无法容纳您所拥有的数据量,则有两种情况:

  1. 您的内存非常低,大多数讨论都是徒劳的,因为您需要完全不同的方法来处理仅有的几个字节。如果您正在处理资源极为有限的嵌入式系统,就会出现这种情况
  2. 您有太多的数据,使用T[n]std::array<T, n>不会有多大帮助,因为我们所说的开销通常小于32字节

也许你可以描述一下你实际上想做什么,以及为什么std::vector<T>不是一个选项。