我们都知道,在c++中,用类去定义对象时,系统会为每一个对象分配存储空间。
因此,按理说,在一个既有数据又有成员函数时,用同一个类定义多个对象时分配内存应该是下面这种情况:
然而很明显这种方法,有一个重大缺陷:当对象定义比较多时,将在存储每一个对象中均出现数据和成员函数,而这些成员函数除了仅仅执行的对象不同,其余代码内容完全相同,很明显,一个相同的代码在每个对象中都存储,这样造成的内存资源大量浪费是很不必要的。。。显然这种方法是不可取的。
因此在c++中,采取的方法是:对象在存储时仅仅存储的为它的数据部分,而他的函数部分存储的是另一块存储空间;
一个对象所占的空间大小只取决于该对象中数据成员所占的空间,而与成员函数无关。在调用各对象的函数时,都会去调用这个公共的函数,从而大大节约存储空间。即下图方式:
但是,这样存储固然有很大优势,但是,又有了一个新的问题:即对象使用时,当相同的成员函数引用不同的数据成员时,怎样能保证引用的是所指向的对象的数据成员呢?
在c++中解决这个问题,在每个成员函数中都包含一个特殊的指针,这个指针的名字是固定的,即this指针。。。它是指向本类对象的指针,它的值是当前被调用的成员函数所在对象的起始地址。。
举一个例子进行说明:
程序:
#define _CRT_SECURE_NO_WARNINGS 1
#include <iostream>
#include <string>
using namespace std;
class Student
{
private:
char _name[20];
char _sex[5];
int _age;
public:
void InitStudent(char* name, char* sex, int age)//初始化函数
{
strcpy(_name, name);
strcpy(_sex, sex);
_age = age;
}
void PrintStudent() //打印函数
{
cout << _name << " " << _sex << " " << _age << endl;
}
};
int main()
{
Student s1,s2,s3;
s1.InitStudent("小明","男",18);
s1.PrintStudent();
s2.InitStudent("张三", "女", 17);
s2.PrintStudent();
s3.InitStudent("李四", "男", 20);
s3.PrintStudent();
system("pause");
return 0;
}
调试程序:
1.当程序执行创建对象s1时,打开监视我们取s1地址,然后调试程序进入对对象s1进行操作的成员函数,在监视中同样取
this指针的地址
利用同样的方法对对象s2的地址和对s2数据成员进行操作的成员函数中取this的地址
同样s3也相同。。。
通过对比可以很清晰的看到此时this指针所存的地址就是第一个对象的地址,我们都知道在程序编译的时候编译器会重新对代码进行重写,在重写的时候,编译器将会在类的成员函数参数中添加this指针参数。
比如:上边函数
void InitStudent(char* name, char* sex, int age)//初始化函数
{
strcpy(_name, name);
strcpy(_sex, sex);
_age = age;
}
在编译器看来,函数将如下形式:
void InitStudent(Student* const this ,char* name, char* sex, int age)//初始化函数
{
strcpy(this->_name, name);
strcpy(this->_sex, sex);
this->_age = age;
}
用this指针将对象的起始地址传给成员函数,进而进行操作。
在vs编译器下打开反汇编也可看到函数进行对对象进行操作时,this指针的变化。。
即this指针先将对象的起始位置传给成员函数,这样成员函数引用数据成员时,就会按照this指针的指向找到对象的数据进行操作。。。
需要注意的是:this指针的类型是*const形;
this指针是类的成员函数独有的,一般函数无this指针;
this指针的生命周期和成员函数的参数的生命周期相同;
this指针是隐式使用的,它作为参数被编译器自动传递给成
员函数;