C++ class 对象的总内存
total memory of a C++ class object
为什么下面这段代码的答案是24?即,classX后面的对象的总大小是多少,24字节?我使用的是 64 位机器。
#include <bits/stdc++.h>
using namespace std;
class X
{
vector <bool> f;
int b;
public:
X(){
f.push_back(true);
}
};
int main(){
X ob;
cout<<sizeof(ob);
return 0;
}
vector 维护自己的内部变量用于簿记和分配器。
将您机器上 int
的大小与向量的大小相加得到总和。
注:
关于 int,指针的大小在任何 64 位 C/C++ 编译器上都应为 8 字节,但不一定是 int 的大小。
您可以在此处查看 vector(对于 gcc)的内部结构以进行快速查找:
https://gcc.gnu.org/onlinedocs/gcc-4.6.3/libstdc++/api/a01115_source.html
That is, how is the total size of the object of following class X, 24
bytes? I'm using 64-bit machine.
C++ 几乎不保证类型大小,none 不保证标准容器的内存布局。因此,对于此类问题,说明您的编译器和调用它的选项也很重要。
class X
{
vector <bool> f;
int b;
public:
X(){
f.push_back(true);
}
};
您可以查看 sizeof(int)
和 sizeof(vector<bool>)
的单独结果。他们可能会透露以下内容:
- 8 个字节用于
int b
。
- 16 个字节用于
vector<bool> f
。
vector<bool>
的 16 个字节更难分析。一些东西 可以 存储在对象中,例如:
- 您 "invisibly" 在构造向量时通过默认参数传递的
std::allocator<bool>
实例。
- 指向数据占用的动态分配内存开始的指针,表示向量的
bool
个元素。
- 指向该内存末尾的指针(对于恒定时间
capacity()
调用)。
- 指向动态分配内存中最后一个元素的指针(对于恒定时间
size()
调用)。
- 当前元素数或当前容量数(对于恒定时间
size
和 capacity()
调用)。
如果您想确定地知道,您可能可以查看您的实现的头文件,看看您的编译器如何在内存中布局 std::vector<bool>
。
请注意,由于 special optimisations,std::vector<bool>
的内存布局可能不同于所有其他 std::vector
。例如,在我使用 MSVC 2013 的机器上,仅使用 cl /EHsc /Za /W4 Whosebug.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 位机器上 运行s 的信息是不够的。
[*] std::vector<bool>
应该是一个 space 高效的优化,但显然在这个实现中这只涉及to space 由动态分配的元素占用,而不是向量本身的静态大小。
为什么下面这段代码的答案是24?即,classX后面的对象的总大小是多少,24字节?我使用的是 64 位机器。
#include <bits/stdc++.h>
using namespace std;
class X
{
vector <bool> f;
int b;
public:
X(){
f.push_back(true);
}
};
int main(){
X ob;
cout<<sizeof(ob);
return 0;
}
vector 维护自己的内部变量用于簿记和分配器。
将您机器上 int
的大小与向量的大小相加得到总和。
注:
关于 int,指针的大小在任何 64 位 C/C++ 编译器上都应为 8 字节,但不一定是 int 的大小。
您可以在此处查看 vector(对于 gcc)的内部结构以进行快速查找: https://gcc.gnu.org/onlinedocs/gcc-4.6.3/libstdc++/api/a01115_source.html
That is, how is the total size of the object of following class X, 24 bytes? I'm using 64-bit machine.
C++ 几乎不保证类型大小,none 不保证标准容器的内存布局。因此,对于此类问题,说明您的编译器和调用它的选项也很重要。
class X { vector <bool> f; int b; public: X(){ f.push_back(true); } };
您可以查看 sizeof(int)
和 sizeof(vector<bool>)
的单独结果。他们可能会透露以下内容:
- 8 个字节用于
int b
。 - 16 个字节用于
vector<bool> f
。
vector<bool>
的 16 个字节更难分析。一些东西 可以 存储在对象中,例如:
- 您 "invisibly" 在构造向量时通过默认参数传递的
std::allocator<bool>
实例。 - 指向数据占用的动态分配内存开始的指针,表示向量的
bool
个元素。 - 指向该内存末尾的指针(对于恒定时间
capacity()
调用)。 - 指向动态分配内存中最后一个元素的指针(对于恒定时间
size()
调用)。 - 当前元素数或当前容量数(对于恒定时间
size
和capacity()
调用)。
如果您想确定地知道,您可能可以查看您的实现的头文件,看看您的编译器如何在内存中布局 std::vector<bool>
。
请注意,由于 special optimisations,std::vector<bool>
的内存布局可能不同于所有其他 std::vector
。例如,在我使用 MSVC 2013 的机器上,仅使用 cl /EHsc /Za /W4 Whosebug.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 位机器上 运行s 的信息是不够的。
[*] std::vector<bool>
应该是一个 space 高效的优化,但显然在这个实现中这只涉及to space 由动态分配的元素占用,而不是向量本身的静态大小。