先看如下代码:
#include<iostream>
#include<stdlib.h>
using namespace std;
class Person
{
public:
void SetPersonInfo(const char* name, const char* gender, int age)
{
strcpy(_name, name);
strcpy(_gender, gender);
_age = age;
}
void PrintPersonInfo()
{
cout << _name << " " << _gender << " " << _age << endl;
}
private:
char _name[20];
char _gender[3];
int _age;
};
int main()
{
int ret = 0;
Person p1, p2, p3;
p1.SetPersonInfo("张三", "男", 19);
p2.SetPersonInfo("李思", "女", 20);
p3.SetPersonInfo("王武", "男", 21);
p1.PrintPersonInfo();
p2.PrintPersonInfo();
p3.PrintPersonInfo();
ret = sizeof(p1);
cout << "类的大小是:" << ret << endl;
system("pause");
return 0;
}
运行结果:
问题:类中既有成员变量,又有成员函数,那么一个类的对象中包含了什么?如何计算一个类的大小?
针对上面代码设计的对象的三种存储方式,分析对比找出合理的存储方式。
存储方式一:
类对象中包含类的各个成员,如下图所示:
分析:每个对象中的成员变量是不同的,但是函数都是相同的。如果一个类创建多个对象,每个对象中都会保存一份代码,相同代码保存多次,则浪费空间。
问题:能否将代码只保存一份,调用时编译器只要能够找到函数的入口地址即可?
存储方式二:
多给一个指针存放成员函数表的首地址,如下图所示:
分析:方式二明显比方式一节省了很多空间,但是对象中还是多了一个指针。
存储方式三:
只保存类的具体成员变量,成员函数统一的存放在代码公共区,如下图所示。
问题:对于上述三种存储方式,计算机到底按那种方式存储?
分析:通过不同对象分别获取其大小,如下代码所示。
#include<iostream>
#include<stdlib.h>
using namespace std;
class A1
{
public:
void f1()
{}
void f2()
{}
private:
int _a;
};
class A2
{
public:
void f1()
{}
void f2()
{}
};
class A3
{};
int main()
{
A1 a1;
A2 a2;
A3 a3;
cout << "sizeof(A1)=" << sizeof(A1) << endl;
cout << "sizeof(A2)=" << sizeof(A2) << endl;
cout << "sizeof(A3)=" << sizeof(A3) << endl;
system("pause");
return 0;
}
运行结果为:
结论:一个类的大小实际就是该类中成员变量之和其中要进行内存对齐。
注意:空类的大小时一个字节,编译器用来唯一标识这个类。如果这个类占4个字节就太浪费内存空间了;如果占用0字节,编译会报错。
类对象的存储模型:
结构体内存对齐规则
(1)第一个成员在与结构体偏移量为0的地址处;
(2)其他成员变量要对齐到某个数字(对齐数)的整数倍的地址处。其中,对齐数=编译器默认的一个对齐数与该成员大小的较小值成倍数关系。VS中默认的值为8,gcc中默认值为4。
(3)结构体总大小为最大对齐数的整数倍,每个成员变量除了第一个成员都有一个对齐数。
(4)如果嵌套了结构体,那么嵌套的结构体将对齐到最大对齐数的整数倍,结构体的整体大小就是最大对齐数的整数倍(含嵌套结构体的对齐数)。
注意:内存对齐是为了存储数据方便,用空间换取时间,提高系统的性能。可通过“#pragma pack(n)”设置对齐参数进行内存对齐。
#include<iostream>
#include<stdlib.h>
using namespace std;
class A
{
char ch;
double d;
};
class B
{
char ch1;
A a;
char ch2;
};
int main()
{
cout << sizeof(A) << endl;
cout << sizeof(B) << endl;
system("pause");
return 0;
}
运行结果:
C++中的struct和class有什么区别?
C++中的struct默认的访问限定符是public,而class是private。
C语言中的struct和C++中的struct有什么区别?
C语言中的struct没有成员函数,不能继承,也没有访问限定符,但是C++中的struct有。
为什么C++中有了class,还要有struct?
因为C++是在C语言的基础上演变而来,C语言是面向过程的语言,而C++是面向对象的语言。C++提供struct是为了能与C语言兼容。