クラスオブジェクトのサイズを計算する方法についての記録をここに。
おそらくまとめ、クラスのサイズは、次の点を考慮します
- 非静的メンバ変数のサイズ
- データのビット数に合わせ
- 仮想関数かどうか(すなわち、仮想関数テーブルポインタをどのように多くのポイントを見て必要性を継承継承の場合を考えると、仮想関数テーブルへのポインタである必要はありません)
非静的メンバ変数のサイズ
空のクラス
まず、とき何の例を見て:
class test{
};
オブジェクトクラスのインスタンスのサイズは1で、見ることができます。クラスは空のクラスがあるにもかかわらず、割り当てられていない場合、コンパイラ割り当てAバイト占有スペース、そして実際にインスタンス化されたすべての後にオフのブランク/空の変数の実際の差(のは、一部のメモリ領域を割り当てるためです宇宙、それはほとんどインスタンス化せずになります)。空白のクラスは基本クラスとして継承されている場合でも、ノート、そして、瞬間を継承しているその継承クラスのスペース、基底クラスのサイズ0に影響を与え、そのクラスを継承して行くことはないだろう唯一の変数(ここではデフォルトは単一継承である)について、自身のメンバーにサイズ:
#include <iostream>
#include <string>
using namespace std;
class test {
};
class test2 : public test {
private:
int a = 2;
};
int main() {
test2 tmp;
cout << "size of class test " << sizeof(tmp) << endl;
getchar();
return 0;
}
唯一のメンバ変数
#include <iostream>
#include <string>
using namespace std;
class test3 {
private:
int a = 3;
float b = 3.0;
};
int main() {
test3 tmp;
cout << "size of class test " << sizeof(tmp) << endl;
getchar();
return 0;
}
システム32は、見ることができるint
とfloat
4バイトなので、クラス8の最終的なインスタンスのサイズが。
クラスの大きさの静的な静的メンバ変数の影響
#include <iostream>
#include <string>
using namespace std;
class test4 {
private:
int a = 3;
float b = 3.0;
static int c;
};
int main() {
test4 tmp;
cout << "size of class test " << sizeof(tmp) << endl;
getchar();
return 0;
}
私たちも、静的メンバ変数で、出力はまだ8で、見ることができます。場所は実際にあるので、それは、インスタンスのサイズには影響しませんので、これは静的メンバ変数は、(グローバル変数/スタティック変数エリア、すべての後に、目に見えるすべてのインスタンスを作るために)別の場所に保管されています。
唯一のメンバ関数
class funcOnly {
public:
funcOnly() {};
~funcOnly() {};
private:
void boo() {};
};
、関数はコンパイラが1つのバイトのプレースホルダが割り当てられているので、1である場合、空間クラスを占有していない見ることができます。我々はまた、次の確認できます。
したがって、4バイトに1バイトから空間クラス、1バイトのように、もはや空のクラス。
データのビット数に合わせ
class test5 {
private:
char d;
int a = 3;
float b = 3.0;
static int c;
};
int main() {
test5 tmp;
cout << "size of class test " << sizeof(tmp) << endl;
getchar();
return 0;
}
がchar
1バイトのみを占有するが、なぜならプレゼンスデータアライメントは、4の倍数(パディングに必要なパディングであるchar
4バイトに、CPUは、便宜上を算出します)。さらに、そこかもしれない実際には、このような連続する2つのような分化のいくつかの他の状況、char
一緒に:
そして、別のリリース:
可以看到,顺序对实例大小的影响。这是因为,如果两个char
放在一起的话,那么编译器会将这两个char
放在一起,然后补齐。如果不是连续放着的,那么会分别补齐到4字节。因此,尽量“凑”变量类型到4字节,这样可以让补齐后的实例大小小一些。另外,要注意的是,含有数组的时候是一个个地连续地放,而不是视为整体,所以如果有数组,例如:
class test8 {
private:
char d[12];
int a = 3;
};
再举个例子:
class test8 {
private:
char d[11];
int a = 3;
};
有数组的时候,先连续摆放好,然后再补齐。
注意,上面说到的补齐到4字节是因为类里面最大的类型就是int
,是4个字节,如果有更大的,那么就要补齐到更大的字节对应的倍数,如:
这里出现了8字节的double
,那么补齐到8字节。其实之所以补齐8字节,是因为我是在Windows平台下编译的,如果是Linux,即是用GCC,那么其实还是当类型大小超过4字节的时候,只要求起始地址是4的整数倍。
有无虚函数
这部分理解要结合虚函数相关的知识。
class funcOnly2 {
public:
funcOnly2() {};
virtual ~funcOnly2() {};
private:
void boo() {};
};
int main() {
funcOnly2 tmp;
cout << "size of class funcOnly2 " << sizeof(tmp) << endl;
getchar();
return 0;
}
这里因为多了个虚指针,所以大小为4,所以类大小要加上虚指针的4:
class funcOnly2 {
public:
funcOnly2() {};
virtual ~funcOnly2() {};
private:
void boo() {};
int br;
};
例如上面这样的,就是int
的4加上虚指针的4。
总结
大概总结下,类的大小需要考虑以下内容:
- 所有非静态成员变量大小
- 数据对齐到多少位
- 有无虚函数(即需不需要指向虚函数表的指针,如果考虑继承的情况,则还需要看继承了多少个指向虚函数表的指针)
参考
C++中空类占一字节原因详解:建议看,对空白类的讲解比较详细
sizeof计算空间大小的总结
《C++ Primer 第5版》