为什么没有成员变量的C++类会占用空间
Why do C++ classes without member variables occupy space?
我发现,即使类是一个没有成员变量(或只有静态成员变量)的谓词,MSVC和GCC编译器也会为每个类实例分配至少一个字节。以下代码说明了这一点。
#include <iostream>
class A
{
public:
bool operator()(int x) const
{
return x>0;
}
};
class B
{
public:
static int v;
static bool check(int x)
{
return x>0;
}
};
int B::v = 0;
void test()
{
A a;
B b;
std::cout << "sizeof(A)=" << sizeof(A) << "n"
<< "sizeof(a)=" << sizeof(a) << "n"
<< "sizeof(B)=" << sizeof(B) << "n"
<< "sizeof(b)=" << sizeof(b) << "n";
}
int main()
{
test();
return 0;
}
输出:
sizeof(A)=1
sizeof(a)=1
sizeof(B)=1
sizeof(b)=1
我的问题是编译器为什么需要它?我能想到的唯一原因是确保所有成员var指针都不同,这样我们就可以通过比较指向A或B类型的两个成员的指针来区分它们。但在处理小型集装箱时,这样做的成本相当高。考虑到可能的数据对齐,我们可以在没有vars(?!)的情况下获得每个类最多16个字节。假设我们有一个自定义容器,它通常会包含一些int值。然后考虑一组这样的容器(大约有1000000个成员)。开销将是16*1000000!发生这种情况的一个典型情况是,一个容器类的成员变量中存储了一个比较谓词。此外,考虑到类实例应该总是占用一些空间,在调用a()(value)时应该期望什么类型的开销?
必须满足C++标准中的一个不变量:相同类型的每个C++对象都需要有一个唯一的地址才能识别。
如果对象不占用空间,那么数组中的项将共享相同的地址。
基本上,它是两个需求之间的相互作用:
- 同一类型的两个不同对象必须位于不同的地址
- 在数组中,对象之间可能没有任何填充
注意,仅第一个条件不需要非零大小:给定
struct empty {};
struct foo { empty a, b; };
第一个要求可以通过具有一个零大小的a
后跟一个单个填充字节以强制不同的地址、后跟一个零尺寸的b
来容易地满足。然而,给定
empty array[2];
因为不允许在不同对象CCD_ 3和CCD_。
所有完整的对象都必须有一个唯一的地址;因此,它们必须至少占用一个字节的存储空间,即位于其地址的字节。
发生这种情况的一个典型情况是,一个容器类的成员变量中存储了一个比较谓词。
在这种情况下,您可以使用空基类优化:允许基子对象与它所属的完整对象具有相同的地址,因此不会占用任何存储空间。因此,您可以将谓词作为(可能是私有的)基类而不是成员附加到类。这比会员更麻烦处理,但应该可以消除开销。
调用A()(value)时应该期望什么类型的开销?
与调用非成员函数相比,唯一的开销是传递额外的this
参数。如果函数是内联的,那么应该消除这种情况(通常情况下,在调用不访问任何成员变量的成员函数时也是如此)。
已经有很好的答案回答了主要问题。我想谈谈你表达的担忧:
但在处理小型集装箱时,这样做的成本相当高。考虑到可能的数据对齐,我们可以在没有vars(?!)的情况下获得每个类最多16个字节。假设我们有一个自定义容器,它通常会包含一些int值。然后考虑一组这样的容器(大约有1000000个成员)。开销将是16*1000000!发生这种情况的一个典型情况是,一个容器类的成员变量中存储了一个比较谓词。
避免持有A
的成本
如果容器的所有实例都依赖于类型A
,则无需在容器中保存A
的实例。与A
的非零大小相关联的开销可以通过在需要时在堆栈上简单地创建A
的实例来避免。
无法避免持有A
的成本
如果A
是多态的,那么您可能会被迫在容器的每个实例中保留一个指向A
的指针。对于这样一个容器,每个容器的成本增加了一个指针的大小。基类A
中是否有任何成员变量对容器的大小没有影响。
sizeof A
的影响
在任何一种情况下,空类的大小都不应与容器的存储要求有关。
- 常量"C"占用的空间(以字节为单位)
- 为什么QT的iOS组件会占用这么多磁盘空间?
- 为什么树结构比其节点的总和占用更多的空间
- 当编译时已知引用占用结构中的空间时,是否错过了优化?
- 空向量占用的空间是否与指向当前设置为 nullptr 的类型的指针一样多
- 如何使一种类型的STL对只占用另一种类型的空间"empty struct"?
- iostream 是否占用堆栈空间
- 什么占用更多空间:对象或结构
- 解除分配 stl 占用的空间
- 清除stdin缓冲区(内存占用空间)
- 5字节QByteArray的内存占用空间.5字节的quint64或QByteArray存储效率更高吗
- 为什么没有成员变量的C++类会占用空间
- std::shared_ptr 占用的内存空间比 vector 多得多
- 无序的地图占用大量空间
- 为什么linux在分配动态内存时会占用一些额外的空间
- 删除指针后,str 指针自身的占用空间可以存在
- 如何计算下列结构体所占用的内存空间
- 从技术上讲,对象是否可以占用不连续字节的存储空间
- 带有虚函数的类占用更多空间
- 用于存储占用1位空间的位的C hack