C++深入浅出讲解隐藏this指针的用法
本篇文章我们将一起讨论在有趣的知识点--隐藏的this指针。本篇我们要使用到之前我们所学习到的C++类与对象,如果有各位小伙伴还不曾了解类与对象的简单思想,可以访问上篇:C++深入讲解类与对象之OOP面向对象编程与封装
在之后的学习中,我们将认识一个新的类:日期类Date。正如我们所想的那样,传入一个日期,我们可以输出我们所输入的日期。
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(2022, 5, 11); d2.SetDate(2022, 5, 12); d1.Display(); d2.Display(); return 0; }
输出结果:
我们首先可以通过汇编来看看,d1,d2调用的函数是否相同。
我们可以发现,最终打印的时候调用的Display()是同一个函数,那么既然d1,d2调用的都是同一个函数,编译器如何知道d1是2022-5-11,d2是2022-5-12呢?Display()都访问的_year,_month,_day。而且去公共代码区访问的Display(),这是为什么呢?
这是因为C++在这段代码中做出手脚,C++在这里增加了一个this指针,这里是因为Display会增加一个this形参。C++编译器给每个“非静态的成员函数“增加了一个隐藏的指针参数,让该指针指向当前对象(函数运行时调用该函数的对象),在函数体中所有成员变量的操作,都是通过该指针去访问。只不过所有的操作对用户是透明的,即用户不需要来传递,编译器自动完成。
在调用的时候也传的是各自的地址。这样就十分清晰明了了。这就是隐含的this指针
注意:我们不能显示的写出来,因为他是隐含的,我们不能抢了编译器的活。但是我们可以直接在类里面用。
2.this指针的特性
在真正的编译器中this指针的用const修饰的,this指针本身是不能被修改的,但是内容是可以修改的。并且我们是可以使用的
我们可以在类中打印一下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(2022, 5, 11); d2.SetDate(2022, 5, 12); d1.Display(); d2.Display(); return 0; }
运行结果:
并且我们还能这样写,但是我们不能显示的写出Date* this。
我们接下来再看看this指针是不能修改的,大家看下面这个能过吗?答案肯定是不能的,因为this是被const修饰的,不能修改this指针的。
我们会发现 编译器也会报错:error C2106: “=”: 左操作数必须为左值
this指针的特性总结:
1. this指针的类型:类类型* const。
2. 只能在“成员函数”的内部使用。
3. this指针本质上其实是一个成员函数的形参,是对象调用成员函数时,将对象地址作为实参传递给this形参。所以对象中不存储this指针。
4. 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
原因:Show()函数是存在公共代码区中,编译的时候在公共代码区中找到这个函数,和普通的函数调用是一样的,只需要call函数地址就行。我们发现这里p是空指针,传过去的this指针只是接收了p的空指针,就类似于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
原因:此程序崩溃是在PrintA()中,会隐含一个this->_a,而this指针是一个空指针,访问this指针_a的位置,就要对空指针进行解引用,此时就会崩溃。我们也可通过调试观察到。
(3)this指针是存在哪里的?
a.栈 b.堆 c.静态区 d.常量区
答案:a
解释:this指针是个形参,形参是在函数的栈桢里,在函数的栈桢里面的变量是属于栈中的。
有时编译器会使用寄存器对其进行优化,this指针会存在寄存器中。
到此这篇关于C++深入浅出讲解隐藏this指针的用法的文章就介绍到这了,更多相关C++this指针内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!
最新评论