为什么向量指针会占用如此多的内存?

时间:2013-02-27 14:37:47

标签: c++ vector stl boolean

我正在开展一个项目,我需要尽可能地了解内存使用情况。我正在尝试计算示例中vector<bool>大小32的总大小:

vector<bool> v(32);
cout << "sizeof: " << sizeof(v) << endl;
cout << "size: " << v.size() << endl;
cout << "capacity: " << v.capacity() << endl;
cout << "max_size: " << v.max_size() << endl;

给了我:

sizeof: 40                     <- 40 byte? wtf?
size: 32                       <- hoping an element takes up 1 bit
                                  (instead of the usual 1 byte for booleans)
                                  this should take around 32 bit memory
capacity: 64                   <- I guess this is because minimum size is
                                  1 integer = 64 bit
max_size: 9223372036854775744  <- relevant somehow?

在我的64位ubuntu 12.04机器上。所以我想我可以这样计算内存:

40 * 8 + 64 * 1 = 384 bit = 48 byte

因此,根据此计算,大部分内存花费在大小为32的矢量对象上。我的问题是为什么vector对象需要使用如此多的内存?我的计算中也有错误吗?如果不对32周围的矢量大小进行按位操作,我怎样才能更有效率?

6 个答案:

答案 0 :(得分:4)

这40个字节是管理开销。除其他事项外,vector必须跟踪其sizecapacity(已经消失了两个size_t个字节),非常重要的是指向实际数据!

向量保存的实际数据由默认向量分配器在堆上分配,其内存消耗不包含在sizeof的结果中。

答案 1 :(得分:3)

sizeof(v)的结构大小为v,而不是v数据的大小。这就像在做:

struct S { int* x };

S s;
s.x = new int[10000];

sizeof(s); // only the size of int* (it doesn't/can't check how much data is allocated)

至于为什么std::vector<bool>可能具有比std::vector<int>更大的结构大小,请记住bool版本是专门的。它必须有一些额外的成员来保持按位记录。

答案 2 :(得分:1)

  • v.size()返回vector中可存储的元素数。不是与内存大小直接相关的
  • v.capacity()返回为向量分配的内存单元格数量。向量会提前分配一些内存,但最初并非所有内存都可以访问。不存储器大小直接相关
  • sizeof(v)获取结构本身的字节大小。我想一些指针就在这里。以及大小变量等。

如果你想获取内存元素,那么这可能就是最接近的表达式:v.size() * sizeof(v[0])

答案 3 :(得分:1)

查看g ++实现的来源,我可以找到以下成员:

vector继承自       _Bvector_impl _M_impl;

来自继承的_Bvector_impl

_Bit_iterator   _M_start;   16 bytes
_Bit_iterator   _M_finish;  16 bytes
_Bit_type*  _M_end_of_storage;  8 bytes

总计最多40个字节。

_Bit_iterator包含

_M_offset, an unsigned int: 8 bytes
_M_p,      a pointer 8 bytes. 

答案 4 :(得分:1)

这是您为动态可调整大小的结构支付的价格。 sizeof(v)返回的内容实际上只是向量跟踪存储其数据的动态分配内存的开销。存储数据的空间不包含在该数字中。

如果您在编译时知道项目数,则可以使用std::bitset代替。 std::bitset实际上每个布尔值会使用1位(向上舍入到它使用的字大小)而没有std::vector的开销。

答案 5 :(得分:1)

如果std::vector的大小实际上是在编译时固定的,那么使用std::array代替它可能是有意义的;数组没有任何开销(虽然有填充)。

但是,在bool的特定情况下,您应该考虑std::bitsetbitset按其大小进行参数化,并将bool打包为尽可能高效。它不像打包数组那样具有内存效率(比你自己写的那样),因为它保留了切换位的计数。

liveworkspace演示:

#include <bitset>
#include <array>
#include <vector>

#include <iostream>

int main() {
   std::vector<bool> vec(32);
   std::array<bool, 32> arr;
   std::array<uint8_t, 4> packed;
   std::bitset<32> bs;

   std::cout << "vector: " << sizeof(vec) + vec.capacity()/8 << "\n";
   std::cout << "array : " << sizeof(arr) << "\n";
   std::cout << "packed: " << sizeof(packed) << "\n";
   std::cout << "bitset: " << sizeof(bs) << "\n";
}

给出:

vector: 48
array : 32
packed: 4
bitset: 8

packed显然是最有效的容器,但是bitset提供了一个成本非常低的容器(与64位机器上的指针一样多的空间)。