2

我正在做一个项目,我需要在内存使用方面尽可能地刻薄。vector<bool>我正在尝试计算示例中 a of size的总大小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

所以根据这个计算,大部分内存都花在了 size 的向量对象上32。我的问题是为什么一个vector对象需要使用这么多内存?还有我的计算有什么错误吗?如果不自己对矢量大小进行按位操作,我怎样才能提高效率32

4

6 回答 6

4

这 40 个字节是管理开销。除其他外, avector必须跟踪它的sizeand capacity(这已经是两个size_ts 的字节了),非常重要的是,一个指向实际数据的指针!

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

于 2013-02-27T14:42:40.873 回答
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版本是专门的。它必须有一些额外的成员来保存按位记录。

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

如果您想获取向量元素所占用的内存,这可能是最接近的表达式:v.size() * sizeof(v[0])

于 2013-02-27T14:41:57.130 回答
1

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

向量继承自_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. 
于 2013-02-27T14:49:00.057 回答
1

这就是您为可动态调整大小的结构所付出的代价。返回的sizeof(v)实际上只是向量跟踪其存储数据的动态分配内存的开销。该数字不包括用于存储数据的空间。

如果您在编译时知道项目数,则可以std::bitset改用。std::bitset实际上,您存储的每个布尔值将使用 1 位(四舍五入到它使用的字长),而没有std::vector.

于 2013-02-27T14:51:09.320 回答
1

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

但是,在非常具体的情况下bool,您应该考虑std::bitset!Abitset通过其大小进行参数化,并bool尽可能高效地打包 as。它的内存效率不如打包数组(比您自己编写的),因为它保留了切换位的计数。

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 位机器上的指针一样多的空间)。

于 2013-02-27T14:55:01.137 回答