一,类对象模型
类中既有成员变量,有可能有成员函数,那么一个类的对象之中包含了什么?如何计算一个类的大小?
1,类对象的存储方式
对于不同的类对象,采取的策略是:只保存成员变量,成员函数会保存在公共的代码段之中。
2,类对象的大小
由于类的存储会将函数保存在公共的代码段,所以计算类的大小时不包括成员函数。
一个类的大小,实际就是该类之中“成员变量”之和,并且要遵循内存对齐规则进行对齐。
对于空类,编译器给了空类一个字节来唯一标识这个类。
3,结构体的内存对齐规则
1>第一个成员在与结构体偏移量是0的地址处。
2>其他成员对齐到对其数的整数倍的地址处。
对齐数=min(系统设置的一个默认对齐数,成员大小)
3>结构体的大小是最大对齐数的整数倍
4>如果结构体嵌套结构体,则嵌套的结构体对齐到自己的最大对齐数,整个结构体的大小就是所有最大对齐数的整数倍
二,this指针
1,介绍
同一个类的对象,对象1调用内部成员函数时,成员函数是如何知道其处理的是对象1而不是对象2呢?
C++编译器给每一个“非静态的成员函数”都增加了一个隐藏的指针参数,让该指针指向函数运行时调用该函数的对象,在该函数中的对应对象的成员变量,都是通过该指针去访问的。
this指针用户不需要传递,编译器自动完成。
2,this指针的特性
1>this指针的类型是:类的类型* const
2>只能在“成员函数”内部使用
3>this指针本质上是函数的形参,指向的是对应的对象的地址,对象调用函数时,将对象地址的实参传递给this的形参,所以对象中不存储this指针。
4>this是一个隐含的指针形参,不需要用户传递。
5>this指针存储在栈区,且this指针不可以为空。
3,this为空时的一个例子
class A
{
public:
void print()
{
cout<<_a<<endl;
}
void show()
{
cout<<"show()"<<endl;
}
private:
int _a;
};
int main()
{
A* pa=NULL;
pa->print();
pa->show();
return 0;
}
对于以上这个代码段,我们给一个A类的指针先初始化为空,再借助这个指针访问相关的函数。可以发现以下的现象:调用print是错误的,调用show是没有问题的。
调用show函数时,由于函数没有存储在对象中,并且函数中没有对成员变量的使用,即pa->show这个函数没有对pa进行解引用,所以没有引发空指针访问的崩溃。
但是在调用print时,由于print中要调用成员变量_a,所以会对前面的pa传递过来的this指针进行解引用。但由于pa是空,所以传递到函数中的this指针也会指向空,对空指针解引用会引发报错。
三,类的六个默认成员函数的引出
当创建一个类时,编译器会自动生成一些函数,我们称之为默认成员函数。
任何一个类,即使我们不写的情况下,也会自动生成六个默认成员函数。
这六个成员函数包括:
构造函数:完成初始化工作;
析构函数:完成清理工作;
拷贝构造:使用初始化对象初始化构建对象;
赋值重载:把一个对象赋值给另一个对象;
取地址重载:包括普通对象和const对象两种,这个很少实现。
后续文章对他们进行说明。
本节小结: