数组和向量(64 位)的内存使用情况?

Memory usage for arrays and vectors (64 bit)?

我正在存储大量数据并且想要优化内存。我感到困惑的是以下内容(编译 64 位):

char a[10] = {1,2,3,4,5,6,7,8,9,10};
long long int b[10] = {1,2,3,4,5,6,7,8,9,10};
vector<char> x = vector<char>(10,0);
vector<long long int> y = vector<long long int>(10,0);
cout << sizeof(a) <<" "<< sizeof(b)<< " " <<sizeof(x) <<" "<< sizeof(y)<< endl;

打印值 10 80 24 24。

1) char[10]实际上只使用10个字节吗?它不应该使用 80 个字节吗,因为在 64 位编译中,内存只能为 64 位块寻址?

2) 最后两行:为什么是24(3个字节?)难道只是vector的结构包含了24个字节的数据?

3) 具有 1000 个元素的 chars 向量与具有 1000 个元素的 long long int 向量使用相同数量的内存吗?

1) 一个字符是一个字节。仅仅因为你使用的是 64 位系统 (这意味着它可以使用 64 位地址寻址单个字节,而不是它一次只能 read/write 64 位)。我认为您可能混淆了高速缓存行和内存读取。从内存中读取单个字节,一般会取出64bytes作为一个cache line。与是否访问 1 个字节无关。

2) sizeof returns 的大小 以字节为单位 而不是 以位为单位 。 std::vector 通常实现为 3 个指针的结构,一个用于开始、结束和容量:

struct vector
{
  int* begin;
  int* end;
  int* capacity;
};

由于这是一个 64 位系统,您的指针值 (地址) 将是 8 个字节 (== 64 位)。结果,sizeof 3xpointer 值将为 24 (3 * sizeof(void*))

无论您在向量中存储什么数据类型,sizeof 总是 return 24 (在典型的 64 位架构上)

3) sizeof 只计算数据结构的原始大小。它没有说明该结构内的指针值具有一些额外的动态分配内存这一事实。要获得完整的尺寸,需要这样的东西:

template<typename T>
size_t getUsedMemUsage(const std::vector<T>& vec)
{
  size_t size_of_vector_struct = sizeof(std::vector<T>);
  size_t size_of_single_element = sizeof(T);
  return size_of_vector_struct + size_of_single_element * vec.size();
}
template<typename T>
size_t getFullMemUsage(const std::vector<T>& vec)
{
  size_t size_of_vector_struct = sizeof(std::vector<T>);
  size_t size_of_single_element = sizeof(T);
  return size_of_vector_struct + size_of_single_element * vec.capacity();
}

尽管这并非严格意义上的 (例如 OS 可能会使用一些额外的字节来对齐内存分配,并且可能使用 ~16 字节来跟踪分配).

所以不,1000 个 long long int 的向量将比 1000 个字符的向量使用更少的内存(大约 sizeof(long long int) / sizeof(char)

首先要弄清楚使用的是哪个data model,各种数据类型占用多少内存。

  1. 数组数据占用了一个连续的内存区域,而不会发生对齐,因为所有元素都是同一类型。所以 char[10] 的大小为 10 * 1 = 10 字节。
  2. std::vector在堆上分配内存,即只存储指向分配内存的指针,不存储元素本身。 std::vector本身只存储了指向分配内存的指针,分配内存的大小和元素个数。指针的大小是8个字节,其他元素的大小通常也是8个字节,所以sizeof(std::vector<...>),无论数据类型如何,都会是8 + 8 + 8 = 24 字节。
  3. 其实我上面已经回答了这个问题。 sizeof(std::vector<...>) 实际上与数据类型无关。相反,堆上分配的内存大小取决于数据类型。 std::vector<long long>(1000)std::vector<char>(1000).
  4. 消耗更多内存