即下面X类的对象总大小如何,24
字节?我使用的是 64 位机器。
C++ 很少保证类型大小,也没有保证标准容器的内存布局。因此,对于此类问题,说明您的编译器以及调用它的选项也很重要。
class X
{
vector <bool> f;
int b;
public:
X(){
f.push_back(true);
}
};
您可以查看sizeof(int) 和sizeof(vector<bool>) 的单独结果。他们将可能揭示以下内容:
-
int b 为 8 个字节。
-
vector<bool> f 为 16 个字节。
vector<bool> 的 16 个字节更难分析。有几样东西可以存储在对象中,例如:
-
std::allocator<bool> 的一个实例,您在构造向量时通过默认参数“不可见地”传递。
- 指向数据占用的动态分配内存起点的指针,用于表示向量的
bool 元素。
- 指向该内存末尾的指针(用于恒定时间的
capacity() 调用)。
- 指向动态分配内存中最后一个元素的指针(用于常量时间
size() 调用)。
- 当前元素计数或当前容量计数(用于恒定时间
size 和 capacity() 调用)。
如果你想确定,你可以查看你的实现的头文件,看看你的编译器如何在内存中布置std::vector<bool>。
请注意,由于special optimisations,std::vector<bool> 的内存布局可能与所有其他 std::vectors 不同。例如,在我使用 MSVC 2013 的机器上,仅使用 cl /EHsc /Za /W4 stackoverflow.cpp 编译,sizeof(std::vector<bool>) 是 16 而sizeof(std::vector<int>) 是 12 [*]。
由于实现内部的头文件可能很难阅读,另一种方法是在调试器中运行程序并检查那里的对象。这是 Visual Studio Express 2013 的示例屏幕截图:
如您所见,这里的sizeof(std::vector<bool>) 来自三倍sizeof(unsigned int*),用于指向动态分配内存中第一个元素、最后一个元素和容量结束的指针,加上一个额外的sizeof(unsigned int) 用于元素计数,即由于上述对std::vector<bool> 的特殊优化,这是必要的,这意味着计算指向第一个元素和最后一个元素的指针之间的差异可能不一定会向外部代码揭示向量表示的元素数量。
std::vector<int> 不需要这种特殊处理,这就解释了为什么它更小。
由于Empty base optimization,显然没有考虑继承的std::_Container_base0。
考虑到所有因素,这都是相当复杂的事情。但这就是标准库实现者的世界!请记住,您在头文件中看到的所有内容都是严格内部的。例如,您不能以任何方式假设您自己的代码中存在std::_Container_base0。假装它不存在。
回到你原来的问题,最重要的一点是你的编译器可以以任何它想要的方式布置一个std::vector<bool>,只要它根据 C++ 标准对外部世界表现正确。它也可能选择根本不优化std::vector<bool>。在不了解您的编译器的情况下,我们无法告诉您更多信息。它在 64 位机器上运行的信息是不够的。
[*]std::vector<bool> 应该是一种节省空间的优化,但显然在这个实现中这只涉及动态分配的元素占用的空间,而不是静态大小向量本身。