类方法会增加类实例的大小吗?
Do class methods increase the size of the class instances?
这个问题很直接。为了清楚起见,请考虑下面的示例:
// Note that none of the class have any data members
// Or if they do have data members, they're of equal size, type, and quantity
class Foo {
public:
void foo1();
void foo2();
// 96 other methods ...
void foo99();
};
class Bar {
public:
// Only one method
void bar();
};
class Derived1 : public Foo { };
class Derived2 : public Bar { };
int main() {
Foo f;
Bar b;
Derived1 d1;
Derived2 d2;
return 0;
}
实例f
、b
、d1
和d2
占用相同的内存空间量吗?作为这个问题的扩展,复制Foo
的实例时,传递它需要比Bar
更长的时间,理论上?
只有实例数据会增加类的实例的大小(在我所知道的所有实现中),除非您添加虚函数或从具有虚函数的类继承,那么您需要一次性命中v-table指针。
另外,正如其他人正确地提到的,类的最小大小是1字节。
一些例子:
// size 1 byte (at least)
class cls1
{
};
// size 1 byte (at least)
class cls2
{
// no hit to the instance size, the function address is used directly by calling code.
int instanceFunc();
};
// sizeof(void*) (at least, for the v-table)
class cls3
{
// These functions are indirectly called via the v-table, a pointer to which must be stored in each instance.
virtual int vFunc1();
// ...
virtual int vFunc99();
};
// sizeof(int) (minimum, but typical)
class cls4
{
int data;
};
// sizeof(void*) for the v-table (typical) since the base class has virtual members.
class cls5 : public cls3
{
};
编译器实现可以处理带有多个v表指针或其他方法的多个虚拟继承,因此这些也会对类大小产生影响。
最后,成员数据对齐选项可能会产生影响。编译器可能有一些选项或#pragma
来指定成员数据的起始地址应该是指定字节数的倍数。例如,在4字节边界上对齐并假设sizeof(int) = 4
:
// 12 bytes since the offset of c must be at least 4 bytes from the offset of b. (assuming sizeof(int) = 4, sizeof(bool) = 1)
class cls6
{
int a;
bool b;
int c;
};
严格来说,这是依赖于实现的。但是方法的数量不应该改变类对象的大小。对于非虚方法,对象内存中没有任何与方法指针相关的内容。如果有虚方法,那么每个对象都有一个指向虚函数表的指针。当添加更多方法时,虚函数表会增长,但指针大小保持不变。
进一步说明:对于非虚方法,编译器跟踪每个类的方法指针。当调用非虚方法时,编译器会传递一个指向该对象的方法的指针,或者作为隐藏参数,或者在堆栈上传递。这就是一个方法如何"知道"它的对象并访问this
指针。对于虚方法,方法指针实际上是虚函数表的索引,因此编译器将this
传递给虚函数表中的解引用条目。
会的。实际上在你的例子中,大小是1。在c++中,即使没有任何数据成员,类的大小也为1。
Foo
和Bar
应该各为一个字节。Derived1
和Derived2
可以是一个或两个字节。
原因是编译器将所有静态信息存储在可执行代码中,包括所有成员函数。当您的代码在Foo
的实例上调用foo1
时,它只调用Foo::foo1(this)
,这对于程序中的每个Foo
都是相同的。虚函数是一个例外,但是不要为每个成员函数增加额外的大小,如果有虚函数,只增加一次额外的大小(通常是4/8字节)。
- 从C++实例化QML
- 数组索引的值没有增加
- 在全局变量中保存类的实例以重新创建类(创建"backup")
- OpenGL - 在抛出"__gnu_cxx::recursive_init_error"实例后终止调用?
- 如何在c++中为模板函数实例创建快捷方式
- 在C++中,是否可以基于给定的标识符创建基类的新实例,反之亦然
- 设计一个只能由特定类实例化的类(如果可能的话,通过make_unique)
- 为什么我的代码在输出中增加了93天
- 如何创建一个空的全局类并在启动时实例化它
- 无法创建抽象类的实例
- 多个文件的内存分配错误"在抛出 'std :: bad_alloc' what (): std :: bad_alloc 的实例后终止调用" [C++]
- 在两个类中共享相同的函数调用,并在不需要时避免空实例化
- 我收到以下错误:抛出'std::bad_alloc'实例后终止调用
- 有效地使用std::unordered_map来插入或增加键的值
- 建议在运行时将带有类实例的列表从c++导入qml
- 约束和显式模板实例化
- 通过实例理解std::move及其目的
- 类方法会增加类实例的大小吗?
- 每次实例化泛型类时增加编译时变量
- 为什么字符大小作为实例变量增加