大家好,欢迎来到IT知识分享网。
“用CPU的视角解读this指针的实现原理,看看成员函数背后的秘密”
01
提出问题
在C++的编程实践中,我们经常遇到this指针。它让类(class)的成员函数,可以在函数内部,直接访问类的成员变量,这让类(class)成功实现了数据和函数方法的有效集成,彻底让类(class)和结构体(struct)区别开来。可以说this指针,是面向对象不可或缺的技术基石。
但同时这个this指针也像个幽灵,你说它存在吧,你不知道它从哪里来,到哪里去;你说它不存在吧,任何一个成员函数,都可以凭空变出一个this指针出来,如下面的代码所示:
class A { public: A* mFunc() { return this; } };
虽然很多书籍都对this指针作了解释,阿布也尊重任何版本的解释。但今天,我们只从CPU的视角,再来看看这个问题。或许,你会发现:this指针,比想象中要简单、通透许多。
02
this的产生和传递
打开Compiler Explorer,编写一个世界上最简单的类;再编写一个世界上最简单的成员函数mFunc;然后,我们再写一个世界上最简单的普通函数func;最后,写一个main函数,作一下函数调用,如图所示。

让我们对比一下成员函数和普通函数,看看它们到底有什么区别?
老规矩,你不需要知道汇编指令的意思,我们只比较它们的差异。如你所见,它们的汇编指令完全相同,成员函数跟带参数(thisPointer)的普通函数func在实现细节上是完全一致的。
所以,我们猜:成员函数,应该存在一个“隐藏”的参数,它就是:this指针。现在,你知道this指针是如何凭空产生的吗?this指针是每一个成员函数必备的默认参数,只是C++语法规则,将它隐藏起来了而已。
那是谁给成员函数,输入这个this指针呢?让我们再看看调用部分,如图所示。

显然,调用成员函数与调用普通函数的CPU指令,又是完全一致!所以,从CPU的视角上看:输入this指针,就是输入对象a的内存地址。
当对象调用成员函数时,都会把自己的内存首地址,也就是所谓的this指针,通过CPU寄存器rdi,传递给成员函数。参数传递的具体细节,还可以参看”CPU眼里的:参数传递”。
所以,现在你明白为什么类(class)的成员函数可以访问成员变量了吧,因为成员函数,一旦获得了类对象的内存首地址(this指针),通过适当的偏移,就可以访问相应的成员变量了。如图所示:

其中CPU寄存器rax保存的就是this指针(类对象的内存首地址),以this指针为基准,做0个字节偏移,就是成员变量x的内存首地址;做8个字节偏移,就是成员变量y的内存首地址。
当然,需要注意的是,类(class)的静态成员变量,不是通过this指针,加上一定的偏移来访问的;相反,类(class)的静态成员变量,跟普通的全局变量、静态变量一样,往往有一个独立、固定的内存地址,具体可以参看”CPU眼里的static、global和local”
03
不一样的this指针
但需要注意的是:this指针不是普通的指针变量,它没有明确的内存存储空间,它的值,可能保存在CPU寄存器里面、堆栈里面,甚至代码段中,具体可以查看章节“CPU眼里的:右值”。跟右值一样,我们也不能对this进行赋值操作,例如:
this = nullptr;
但它又能像普通指针变量一样做间接引用,例如:return *this;同样,在没有完全掌握对象生命周期的情况下,贸然传递和销毁this指针,也可能产生内存泄漏、或运行错误,例如:
delete this;
当然这些都是语法规则上面的约定,只要我们能清楚的了解this所代表的信息,明确this所指向的对象是谁,以及this参数产生、传递的过程,我们就可以有效的驾驭它。
04
总结
- this指针不是幽灵,它不能凭空产生。它是每一个成员函数,必须具备的“隐藏参数”,其实现方式,跟有参数的普通函数,完全一致。
- 调用成员函数时,必须为成员函数传递:this指针,也就是该对象本身的内存地址。不要忘了,指针的本质就是内存地址。
- this指针又不是普通的指针变量,在使用的时候,既有右值的特性,也有左值的特性。关注this指针的合法性,就是在关注对象实体的生命周期。
阿布很欣赏 this 这种简洁的语法操作。但如果能大方的承认,成员函数都会多一个隐藏参数this,这样,会不会更清晰呢?
05
热点问题
Q1:this指针的传递,在x86平台上,好像是通过ecx寄存器完成的。
A1:是的,不同平台,不同编译器,不同的调用约定,对参数传递的方式略有不同,但大多都是通过寄存器传递,至于选择什么寄存器,原则上可以随意发挥,但不同编译器,会有自己不同的规则。不过,天下武功,殊途同归,它们要作的事情都是一样的。
Q2:this指针是不是就相当于python的self,只是C++把this参数,省略了?
A1:十分赞同你的思考。很多编程语言,它们都有相似的使用方法和实现逻辑。C/C++更加偏向底层,这也让我们有机会用CPU的视角,细致的观察它的运行细节。
06
更多知识
如果喜欢阿布这种解读方式,希望更加系统学习这些编程知识的话,也可以考虑看看由阿布亲自编写,并由多位微软大佬联袂推荐的新书《CPU眼里的C/C++》
<script type=”text/javascript” src=”//mp.toutiao.com/mp/agw/mass_profit/pc_product_promotions_js?item_id=”></script>
免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://haidsoft.com/169584.html