
目录
小伙伴大家好,今天我们将在这篇文章中讨论一个有趣的知识点--隐藏的this指针。本篇需要用到前面学的C++类和对象(上)的基础,如果大家还不太了解类和对象的基本思想,可以去回顾一下这篇文章【C++】带你一篇了解什么是OPP(面向对象编程),什么是封装?类和对象(上)。
1. this指针的引出
接下来我们学习一个时间类,顾名思义,就是会输出我们输入的时间,我们先看一下这段代码:
class Date { public: void Display() { cout << _year << "-" << _month << "-" << _day << endl; } void SetDate(int year, int month, int day) { _year = year; _month = month; _day = day; } private: int _year; // 年 int _month; // 月 int _day; // 日 }; int main() { Date d1, d2; d1.SetDate(2025, 7, 15); d2.SetDate(2025, 7, 16); d1.Display(); d2.Display(); return 0; }运行结果:
我们通过汇编代码来看一下两次调用的函数是不是同一个(我们之前讲过类对象的储存方式:只储存成员变量,成员函数放在公共代码段):
我们看到两次调用的函数的地址是一样的,那么大家思考一下,既然调用的函数是一样的,那么编译器为什么知道d1是2025-7-15。而d2是2025-7-16呢?
这是因为C++在处理这种情况的时候偷偷地做了手脚,添加了一个this指针,在这里就是Display()函数传入了一个this形参。
事实上,C++会为所有非静态的成员函数增加了一个隐藏的this指针,这个指针用来指向调用当前函数的对象,而对于类中所有成员变量和成员函数的访问,都是通过这个this指针。只不过这些操作对于用户来说是隐藏的,由编译器自动完成。
我们将代码补全来解释可能会清晰一点(注意:代码补全是为了方便理解,不一定满足语法规则):
![]()
这样理解是不是就会好一些,也就是在调用成员函数时候都会往里面传入了一个指针,指向的是当前对象。但是再次提醒,我们不能显式地写出来,不能抢了编译器的活。
2. this指针的特性
在真正的编译器中,this使用const修饰的,也就是说
this本身是无法被修改的,但是它的内容可以被修改,
并且我们是可以直接使用的:
void Display() { cout << this->_year << "-" << this->_month << "-" << this->_day << endl; }我们可以来打印一下this指针,还有d1、d2:
class Date { public: void Display() { //使用this指针 cout << this << endl; cout << _year << "-" << _month << "-" << _day << endl; } void SetDate(int year, int month, int day) { _year = year; _month = month; _day = day; } private: int _year; // 年 int _month; // 月 int _day; // 日 }; int main() { Date d1, d2; cout <<"d1:"<< & d1 << endl; cout <<"d2:"<< & d2 << endl; d1.SetDate(2025, 7, 15); d2.SetDate(2025, 7, 16); d1.Display(); d2.Display(); return 0; }运行结果:
并且我们刚才讨论过了,这个this指针是真实存在的,所以我们是可以直接使用的,当然我并不需要显示地传入参数,直接直接调用即可:
void Display() { cout << this << endl; cout << this->_year << "-" << this->_month << "-" << this->_day << endl; }然后我们来讨论一下this指针的不可修改性,我们看下这段代码能不能编译成功:
void SetDate(int year, int month, int day) { this = nullptr; //将nullptr赋值给this _year = year; _month = month; _day = day; }很显然是错误的,因为前面提到了this是被const修饰的,是不允许被修改的。如果编译的话会爆出这样一个错误:
总结:
this类型:类类型* const
this指针本质上是一个成员函数的形参,是对象在调用成员函数的时候将对象的地址作为实参传毒给this形参,所以对象本身并不储存this指针
this只能在成员函数内部使用
this指针是成员函数第一个隐含的指针形参,一般情况由编译器通过ecx寄存器自动传递,不需要用户传递。
3. 练习一下
(1)下面的程序的运行结果是? A.编译报错 B.运行崩溃 C.正常运行
class A { public: void Show() { cout << "show()" << endl; } private: int _a; }; int main() { A* p = nullptr; p->Show(); return 0; }答案:C
因为之前在讲解类和对象的时候我们讲过,成员函数是储存在公共代码区,调用的时候只需要call函数的地址就行。而虽然我们这里this被赋值了nullptr,也就是this被初始化为空指针而已,只是被允许的,我们看一下运行结果和反汇编结果:
![]()
(2)下面的程序的运行结果是? A.编译报错 B.运行崩溃 C.正常运行
class B { public: void PrintA() { cout << _a << endl; } private: int _a; }; int main() { B* p2 = nullptr; p2->PrintA(); return 0; }答案:B
大家可能有疑问,这不是跟上面一个类型的题目吗,为什么上面那个能够正常运行,这个就会运行崩溃呢?大家注意这两道题的区别,第二道题中存在对成员变量的访问(即this->_a),而成员变量的访问是需要获取对象的地址的(也就是this指针),但是这里的this指针被初始化成了空指针(因为p2被赋值了nullptr),所以这里就变成了对空指针的解引用,自然会报错:
(3)this指针是存在哪里的?A.栈 B.堆 C.静态区 D.常量区
答案:A
解释:
this指针是个形参,形参是在函数的栈桢里,在函数的栈桢里面的变量是属于栈中的。
有时候编译器会使用寄存器对其进行优化,将this指针存放在寄存器中:
下面这图可以更直观的看出涉及的变量的储存位置:
(本篇完)










14万+





