引言
C++中的非静态成员函数有一个第一个默认的参数,那就是今天要总结的this指针了。
类型
既然是一个指针,那么就和其它的指针一样,this指针同样有自己的类型。
假设现在已经有了一个日期类,大体上如下:
如果在成员函数中试图修改thsi的指向,如this = NULL;则编译器会给我们报错。提示thsi不能作为左值。其实这是因为thsi是一个常指针。通过thsi可以访问类中的成员变量,那么this又是指向本类对象的一个指针。所以this指针的类型应当是:class Date { public: Date() { cout << "Date::Date() call" << endl; } Date(int year = 2016, int month = 1, int day = 1) { cout << "Date::Date_int_int() call" << endl; _year = year; _month = month; _day = day; } private: int _year; int _month; int _day; };
类类型 * const
这样一个类型。
作用域
thsi指针的作用域为类成员函数内部,当然前提是得有这样一个this指针。比如静态成员函数中就不存在this指针。
我们可以在this的作用域内访问它:
如上所示,但是这样做没有多大意义,因为通过汇编代码其实可以看出来原来的语句:class Date { public: Date() { cout << "Date::Date() call" << endl; } Date(int year = 2016, int month = 1, int day = 1) { cout << "Date::Date_int_int() call" << endl; this->_year = year; this->_month = month; this->_day = day; } private: int _year; int _month; int _day; };
编译器会自动将它重写为我们之前修改后的样子。_year = year; _month = month; _day = day;
函数传参
讲this指针的传参方式时先普及一下有关函数的调用规范(调用约定):
函数调用规范决定了函数调用的实参压栈、退栈及堆栈释放的方式,以及函数名改编的方案,也即命名规范。Windows环境下常用的调用规范有:
1. _cdecl:这是C++/C函数默认的调用规范,参数从右向左依次传递并压入堆栈,由调用函数负责堆栈的清退,因此这种方式利于传递个数可变的参数给被调用得到函数(因为只有调用函数才知道它给被调用函数传递多少个参数以及它们的类型)。如printf()函数(函数的实现不需要知道实参的具体类型和个数)。
2 ._stdcall:这是Win Api函数使用的调用规范。参数从右向左依次传递并压入堆栈。由被调用函数负责堆栈的清退。该规范生成的函数代码比_cdecl更小,但当函数有可变个参数时会转为_cdecl规范。在Windowos中,宏WINAPI、CALLBACK都定义为_stdcall。
3. _thiscall:是C++非静态成员函数的调用规范。不能使用个数可变的参数。当调用非静态成员函数的时候,this指针直接诶保存在ecx寄存器中而非压入函数堆栈。其它方面与_stdcall相同。
4. _fastcall:该规范所修饰的函数的实参将被直接传递到CPU寄存器中而不是内存堆栈中(这就是快速调用的含义)。堆栈清退由被调用函数负责。该规范不能用于成员函数---------------------------------《高质量C/C++》
this指针是类成员函数默认的第一个隐式参数。参数个数确定(非可变参数列表)时:采用_thiscall调用约定,参数由右向左依次压栈,this指针通过ecx寄存器传参;参数个数不确定(可变参数列表)时,采用_cdecl调用约定,参数由右向左依次压栈,this指针在最后通过压栈传递(因为是第一个参数,又采用了_cdecl调用约定)。
const修饰的成员函数
带const修饰的成员函数中,不能修改对象的值,其实就是用const修饰了this指针,即为如下类型:
const 类类型 * const
C++this指针
最新推荐文章于 2021-01-26 03:19:48 发布