我正在开展一个项目,我需要尽可能地了解内存使用情况。我正在尝试计算示例中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
周围的矢量大小进行按位操作,我怎样才能更有效率?
答案 0 :(得分:4)
这40个字节是管理开销。除其他事项外,vector
必须跟踪其size
和capacity
(已经消失了两个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::bitset
! bitset
按其大小进行参数化,并将bool
打包为尽可能高效。它不像打包数组那样具有内存效率(比你自己写的那样),因为它保留了切换位的计数。
#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位机器上的指针一样多的空间)。