1.当类中没有虚函数也没有成员变量的时候,这个类是一个空类,但是sizeof空类对象的大小,并不是为0,而是为1,即默认空类是有一个占位符的。例如:class A{}; sizeof(A) = 1;
注意:sizeof是操作符而不是函数,作用是判断数据类型或着表达式长度,字节数的计算在程序的编译时进行,而不是在程序执行的过程中才计算出来。
2.当类中只含有静态成员变量,如class A{static int a;}; sizeof(A)=1,这是因为静态成员变量是分配在全局存储区的,所以A类相当于空类,只有一个占位符的大小;
3.class A{virtual test(){}}; sizeof(A)=4;任何含有虚函数的类都有一个虚函数表指针vptr,用来指向虚函数表因此大小为4;
4.class A{int a; char aa}; sizeof(A)=8;高位对齐
5.class C:virtual public A{ };sizeof(C)=4;对于虚拟继承的类拥有虚函数表,所以空类C含有虚函数表指针vptr;
6.如果累作为派生类,它有多少个父类,每个父类的大小加起来再加上自身就是sizeof的值得大小;
7.需要说明的是:
(1)类本身是不占用内存的,但是类本身是有大小的,只有类的实例才能占内存。类的元素氛围两种:类的成员变量(存储在栈区或堆区),类的函数(存储在代码区)。所有的函数都是存放在代码区的,不管是全局函数还是成员函数,静态成员函数也是存储在代码区的,它与普通成员函数的区别是:参数中第一个位置没有this指针,因此不能访问非静态成员变量
(2)sizeof不能求得动态分配(使用new 或者malloc分配的)的内存的大小,只能测出静态数组的长度,如下:
int * a = new int[10]; sizeof(a) = 4;
void * p = malloc(10); sizeof(p)=4;
(3)void fun(int arr[10]){int n = sizeof(arr);} n=4 原因分析如下:
这里在函数参数传递时,数组被转化成指针了。因为直接传递整个数组的话,那么必然涉及到数组元素的拷贝(实参到形参的拷贝)当数组非常大时,这会导致效率极低,因而只传递数组的地址,那么只需要拷贝4byte的数据了,效率就高很多了。
(4)sizeof与strlen的区别:
strlen(char*)函数求的是字符串的实际长度,它求的方法是从开始遇到第一个‘\0’,如果只定义没有给它赋初值,这个结果是不定的,它从指针指向的首地址一直找下去,直到遇到‘\0’为止。
example1:
char aa[10];
strlen(aa); //结果将不确定,因为没有赋初值
sizeof(aa);//结果为10
exemple2:
char aa[10] = {'\0'};
strlen(aa);//结果为0;
sizeof(aa)//结果为10
exemple3:
char aa[ ] = "LPR";
strlen(aa);//结果为3
sizeof(aa);//结果为4
exemple4:
char*aa = "0123456789";
strlen(aa);//结果为10,该字符串的长度
sizeof(aa);//结果为4
sizeof(*aa);//结果为1,求得第一个字符会占的空间大小
上面大小全是在32位编译器下得到的大小。
32位编译器:
char :1个字节
char*(即指针变量): 4个字节(32位的寻址空间是2^32, 即32个bit,也就是4个字节。同理64位编译器)
short int : 2个字节
int: 4个字节
unsigned int : 4个字节
float: 4个字节
double: 8个字节
long: 4个字节
long long: 8个字节
unsigned long: 4个字节
指针:4个字节
64位编译器:
char :1个字节
char*(即指针变量): 8个字节
short int : 2个字节
int: 4个字节
unsigned int : 4个字节
float: 4个字节
double: 8个字节
long: 8个字节
long long: 8个字节
unsigned long: 8个字节
指针:8个字节