1.空类
空类的大小为1个字节,参看下面实例
class A {};
int main(int argc, char const *argv[])
{
A a;
cout<<"A sizeof is: "<<sizeof(a)<<endl;
return 0;
}
代码输出结果为
A sizeof is: 1
为什么空类大小不为0?主要是为了确保两个不同对象地址不同,必须如此。
类的实例化是在内存中分配一块地址,每个实例在内存中都有一块不同地址。空类也会被实例化,所以编译器会给空类悄悄分配一字节,这样空类实例化以后就有了自己的地址。所以,空类的sizeof结果不能为0而是1。
2.包含虚函数的类
class B {
public:
virtual void func() {}
virtual void func2() {}
void func3() {}
static int n;
int m;
int *p;
};
int main(int argc, char const *argv[])
{
B b;
cout<<"B sizeof is: "<<sizeof(B)<<endl;
return 0;
}
上面代码输出为:
B sizeof is: 24
我们分析一下这个24结果是如何得到的:
1.在类中,虚函数本身不占用类对象存储空间。
2.非静态函数,静态函数,都不占用类对象存储空间。
3.静态成员变量不占用类对象存储空间。
4.如果有虚函数,不管虚函数有多少个,只有一个虚指针vptr。
在类B中:
func, func2两虚函数,占用8个字节(64位系统)
func3不占用类空间
n是静态成员变量,也不占用类空间。
指针p占用8个字节
m是整形,本身4个字节。因为要进行内存对齐,所有需要8个字节。
因此,最终占用内存为:8+8+8=24。
3.派生类的大小
class C : public B {
int nn;
char cc;
virtual void fn() {}
};
int main(int argc, char const *argv[])
{
cout<<"C sizeof is: "<<sizeof(C)<<endl;
return 0;
}
类C继承上面的类B,最后代码运行的结果为
C sizeof is: 32
我们分析一下32怎么来的:
1.普通继承,派生类继承了所有基类的函数与成员,并且按照字节对齐来计算类的大小。
2.虚函数继承,不管如何继承,都继承了基类的vptr。
B类大小是24,C类中虚函数fn继承虚类的vptr,不占用额外空间。int nn占用4个字节,char cc占用1个字节,内存对齐以后,nn与cc占用总共8字节,所以C类总大小为24+8=32。
4.sizeof与strlen区别
sizeof与strlen都是我们平时常用的。注意这两是有很大区别的:
1.首先sizeof是c/c++中的一个单目运算符,而strlen是一个库函数。
2.sizeof计算的是数据类型占据的空间大小,而strlen只是计算字符串的长度。
我们通过一个例子,来具体分析这两者的区别。
#include<iostream>
#include<cstdlib>
using namespace std;
void sizeof_strlen() {
const char *p = "abcdef";
char d[] = "abcdef";
char e[] = {'a', 'b', 'c', 'd', 'e', 'f'};
char f[] = {'a', 'b', 'c', 'd', 'e', 'f', 'g', '\0', 'h'};
printf("%zu %zu\n",sizeof(p),strlen(p));
printf("%zu %zu\n",sizeof(d),strlen(d));
printf("%zu %zu\n",sizeof(e),strlen(e));
printf("%zu %zu\n",sizeof(f),strlen(f));
int nums[] = {1, 2, 3};
printf("%zu\n", sizeof(nums));
printf("%zu\n", strlen(nums));
}
上述代码,大家先稍微思考两分钟,输出结果应该分别是多少??
首先对于char *p,指向的是一个字符串,注意实际存储的是一个字符数组,并且会自动添加’\0’表示字符数组结束。sizeof计算的是指针p本身的长度,因为机器是64位系统,所以sizeof§为8,而strlen§为字符数组的长度(注意需要刨掉’\0’)为6。
对于char d[],同样会将字符串展开为字符数组,并且会自动添加’\0’表示字符数组结束。char为1字节,字符串本身有6个字符,加上添加的’\0’,因此sizeof(d)为7, strlen(d)为6。
char e[]本身就是字符数组,包含6个字符,此时sizeof(e)为6。而strlen(e)求的是字符串长度,默认的是以’\0‘结束。此时找不到’\0’,会输出一个不确定值,比如作者运行的时候输出就为12。
char f[]与char e[]的不同在于,里面有’\0’字符。所以,sizeof(f)为9,而strlen(f)则是’\0’字符前的长度为7。
nums是整形数组,一个整数占4字节,nums有三个元素,sizeof(nums)为12。
而strlen求的是字符串的长度,nums为整形数组,所以strlen(nums)会报错,编译不通过。