C++this指针
一、什么是this指针
一个对象的this指针并不是对象本身的一部分,不会影响sizeof(对象)的结果。this指针作用域是类内部,当类在非静态成员函数中访问类的非静态成员的时候,编译器会自动将对象本身的地址作为一个隐含参数传递给函数。即使程序员没有编写上this指针,编译器在编译的时候也是加上this的,它作为非静态成员函数隐含形参,对各个成员的访问均通过this指针进行。
例:data.SetStudent(1)<===>SetStudent(&data,1),this指针帮助转换。
建立对象时,系统会为每一个对象分配独立的存储空间,也就是给每个对象中的数据成员都分配有自己独立的存储空间。如果对同一个类定义n个对象,则有n组同样大小的空间以存放对象中的数据成员。但对于成员函数来说,对象中的数据成员。一个函数的代码段在内存中只有一份。也就是说,函数的代码段在内存中只有一份。也就是说,同一个类中的不同对象在调用自己的成员函数时,一个类中的不同对象在调用自己的成员函数时,其实它们调用的是同一段函数代码。
二、this指针的作用
this作用域是在类的内部,自己声明一个类的时候,还不知道实例化对象的名字,所以用this来使用对象变量的自身。在非静态成员函数中,编译器在编译的时候加上this作为隐含形参,通过this来访问各个成员(即使你没有写上this指针)。
一种情况就是,在类的非静态成员函数中返回类对象本身的时候,直接使用 return *this;另外一种情况是当参数与成员变量名相同时,如this->n = n (不能写成n = n)。
#include <iostream>
#include <string.h>
using namespace std;
class Student{
public:
void InfoStudent(char *name,char *gender,int age){
//void InfoStudent(Student *const this,char *name,char *gender,int age);
strcpy(_name,name);
strcpy(_gender,gendet);
_age=age;
}
void PrintStudent(){
cout<<_name<<" "<<_gender<<" "<<age<endl;
}
private:
char _name[20];
char _gender[4];
int _age;
};
int main(){
Student Stu;
Stu.InfoStudent("LIU","female",20);
Stu.PrintStudent();
return 0;
}
其中类成员函数:
void InfoStudent(char *name,char *gender,int age);
//真正传参方式
void InfoStudent(Student *const this,char *name,char *gender,int age);
那么,当一个对象调用自己的成员函数是,如何保证成员函数中数据成员的处理是针对自己的数据而不是其他对象的数据成员呢?this指针假设用一个类定义10个对象:编译系统并不是分别为10个对象的数据成员函数分配存储空间,而是仅为每个对象的数据成员分配存储单元,10个对象的成员函数对应的是同一个函数代码段。不论成员函数在类内定义还是在类外定义,成员函数都用以上方式存储。
在每一个成员函数中都包含一个特殊的指针,这个指针的名字是固定的,称为this。
当前被调用的成员函数所在的对象的起始地址。在调用成员函数时,系统隐式地将对象的起始地址传递给成员函数,使this指针得到当前对象的地址。于是在成员函数中对数据成员的引用,就按照this的指向找到对象的数据成员,实现对数据成员的操作。也就是说, 成员函数中数据成员名的前面隐含有“this->” 的指向。
int Box::Volum(){return (l*w*h);}
int Box::Volum(){return(this->l*this->w*this->h);}
假设a是Box类对象,当执行到a.Volum时候,this=&a当执行时int Box::Volum() return (a.l*a.w*a.h);}
三、this指针的两种传参方式:
1.参数压栈:当成员函数的参数为可变时(_cdecl调用约定)
2.ecx寄存器:当成员函数的参数固定时(_thiscall调用约定)
叫this指针而不叫引用:this 指针和引用的底层实现一样但是类的概念在引用之前提出来所以没有用引用代替this指针
this指针也有可能为空:
int main(){
Student s1;
s1.InfoStudent("Liu","female",18);
Student *ps=&s1;
s1.InfoStudent("Hua","male",20);
ps=NULL;
ps->InfoStudent("Tony","female",25);
s1.PrintStudent();
system("pause");
return 0;
}
NULL对象指针可以调用成员函数 通过对象调用成员函数,对象的指针会被传入函数中,指针名为this
NULL对象指针调用成员函数时,只要不访问此对象的成员变量,则程序能够正常运行。
NULL对象指针调用成员函数时,一旦访问此对象的成员变量,则程序会崩溃。
this指针创建时间
this在成员函数开始执行前构造,在成员的执行结束后清除。
this在成员函数的开始执行前构造,在成员的执行结束后清除。
但是如果class或者struct里面没有方法的话,它们是没有构造函数的,只能当做C的struct使用。采用 TYPE xx的方式定义的话,在栈里分配内存,这时候this指针的值就是这块内存的地址。采用new的方式创建对象的话,在堆里分配内存,new操作符通过eax返回分配的地址,然后设置给指针变量。之后去调用构造函数(如果有构造函数的话),这时将这个内存块的地址传给ecx
this指针存放位置?堆、栈、全局变量还是其他地方
this指针会因编译器不同而有不同的放置位置。可能是栈,也可能是寄存器,甚至全局变量。在汇编级别里面,一个值只会以3种形式出现:立即数、寄存器值和内存变量值。不是存放在寄存器就是存放在内存中,它们并不是和高级语言变量对应的。
this指针是如何传递类中的函数?绑定?在函数参数的首参数就是this指针?那么,this指针又如何找打“类实力后的函数的”?
大多数编译器通过ecx寄存器传递this指针。事实上,这也是一个潜规则。一般来说,不同编译器都会遵从一致的传参规则,否则不同编译器产生的obj就无法匹配了。
在call之前,编译器会把对应的对象地址放到eax中。this是通过函数参数的首参来传递的。this指针在调用之前生成,至于“类实例后函数”,没有这个说法。类在实例化时,只分配类中的变量空间,并没有为函数分配空间。自从类的函数定义完成后,它就在那儿,不会跑的。
this指针是如何访问类中的变量?
如果不是类,而是结构体的话,那么,如何通过结构指针来访问结构中的变量呢?如果你明白这一点的话,就很容易理解这个问题了。
在C++中 ,类和结构是只有一个区别的:类的成员默认是private,而结构是public。
this是类的指针,如果换成结构,那this就是结构的指针了。
我们只有获取一个对象后,才能通过对象使用this指针。如果我们知道一个对象this指针的位置,可以直接使用吗?
this指针只有在成员函数中才有定义。因此,你获得一个对象后,也不能通过对象使用this指针。所以,我们无法知道一个对象的this指针的位置(只有在成员函数里才有this指针的位置)。当然,在成员函数里,你是可以知道this指针的位置的(可以通过&this获得),也可以直接使用它。
每个类编译后,是否创建一个类中函数表保存函数指针,以便用来调用函数?
普通的类函数(不论是成员函数,还是静态函数)都不会创建一个函数表来保存函数指针。只有虚函数才会被放到函数表中。但是,即使是虚函数,如果编译器能明确知道调用的是哪个函数,编译器就不会通过函数表中的指针来间接调用,而是会直接调用该函数。