bkx*_*kxp 52 c++ class predicate sizeof
我发现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;
}
Run Code Online (Sandbox Code Playgroud)
输出:
sizeof(A)=1
sizeof(a)=1
sizeof(B)=1
sizeof(b)=1
Run Code Online (Sandbox Code Playgroud)
我的问题是为什么编译器需要它?我能提出的唯一原因是确保所有成员var指针不同,这样我们就可以通过比较它们的指针来区分A或B类型的两个成员.但是在处理小型容器时,这个成本非常严重.考虑到可能的数据对齐,我们每个类最多可以获得16个字节而不需要vars(?!).假设我们有一个自定义容器,通常会包含一些int值.然后考虑一系列这样的容器(大约有1000000个成员).开销将是16*1000000!可能发生的典型情况是容器类,其中比较谓词存储在成员变量中.另外,考虑到类实例应该总是占用一些空间,在调用A()(value)时应该期望什么类型的开销?
Kon*_*lph 74
必须满足C++标准中的不变量:相同类型的每个C++对象都需要具有可识别的唯一地址.
如果对象没有占用空间,则数组中的项将共享相同的地址.
cel*_*chk 26
基本上,它是两个要求之间的相互作用:
请注意,仅第一个条件不需要非零大小:给定
struct empty {};
struct foo { empty a, b; };
Run Code Online (Sandbox Code Playgroud)
通过使用零大小a后跟单个填充字节来强制执行不同的地址,然后是零大小,可以轻松满足第一个要求b.但是,给定
empty array[2];
Run Code Online (Sandbox Code Playgroud)
由于不同对象之间的填充而不允许empty[0],empty[1]因此不再有效.
Mik*_*our 13
所有完整对象必须具有唯一的地址; 所以它们必须占用至少一个字节的存储空间 - 它们的地址为字节.
可能发生的典型情况是容器类,其中比较谓词存储在成员变量中.
在这种情况下,您可以使用空基类优化:允许基础子对象具有与其所属的完整对象相同的地址,因此不占用任何存储空间.因此,您可以将谓词作为(可能是私有的)基类而不是成员附加到类.处理比成员更加繁琐,但应该消除开销.
调用A()(value)时应该期望什么类型的开销?
与调用非成员函数相比,唯一的开销是传递额外的this参数.如果函数是内联的,则应该消除(通常情况下,调用不访问任何成员变量的成员函数时).
| 归档时间: |
|
| 查看次数: |
6869 次 |
| 最近记录: |