我发现MSVC和GCC编译器为每个类实例分配至少一个字节,即使这个类是一个没有成员变量(或者只有静态成员变量)的谓词。以下代码说明了这一点。为什么没有成员变量的C++类占用空间?
#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类型的两个成员。但是在处理小尺寸容器时,这样做的代价非常严重。考虑到可能的数据对齐,我们可以得到每个类没有变量(?!)的16个字节。假设我们有一个自定义容器,通常会容纳几个int值。然后考虑一个这样的容器数组(大约有1000000个成员)。开销将是16 * 1000000!它可能发生的典型情况是一个带有存储在成员变量中的比较谓词的容器类。另外,考虑到类实例应该总是占用一定的空间,调用A()(value)时应该期望什么类型的开销?
只是为了确认您的怀疑:*除非是位域(9.6),否则大多数派生对象的大小应为非零,并占用一个或多个字节的存储空间。基类子对象可能具有零大小。* – chris 2014-09-11 12:00:37
供参考:大小为*的子对象被允许。所以,如果你从这样一个空的类派生出来并添加另一个x的成员,那么你的派生类型的大小也是x。这就是所谓的“空基类优化” – sellibitze 2014-09-11 12:04:26
我相信你有几个问题重叠在那里。没有必要在容器中“存储”大量没有成员的类。毕竟,由于没有数据,它们之间没有区别。但是,没有成员的类在C++中的大小不为零并不意味着有成员的类将会产生不必要的开销。然而,内存对齐问题是一个独立的问题,并不限于C++。 – AlefSin 2014-09-11 12:05:19