1. this 指针的由来
#include <iostream>
using namespace std;
class Date {
// 成员函数
public:
void Init(int year, int month, int day)
{
_year = year;
_month = month;
_day = day;
}
//内部 this 实际是这样的 void Print(Date * const this)
void Print()
{
// this 指针不能显示写,但是我们可以在函数内部使用
cout << this->_year << "年" << _month << "月" << _day << "日" << endl;
}
// 成员变量
private:
int _year;
int _month;
int _day;
};
int main()
{
Date d1, d2;
d1.Init(2024, 3, 4);
d2.Init(2024, 3, 5);
d1.Print();
d2.Print();
return 0;
}
- ① 为什么
Init()
,和Print()
两个函数的地址一样还可以打印出2024年3月4日和2024年3月5日呢? - Date类中有
Init()
与Print()
两个成员函数,函数体中没有关于不同对象的区分,那当d1调用 Init 函数时,该函数是如何知道应该设置d1对象,而不是设置d2对象呢? -
原因如下:
C++中通过引入this指针
解决该问题,即:C++编译器给每个“非静态的成员函数“增加了一个隐藏的指针参数,让该指针指向当前对象(函数运行时调用该函数的对象),在函数体中所有“成员变量”的操作,都是通过该指针去访问。
只不过所有的操作对用户是透明的,即用户不需要来传递,编译器自动完成。
- 隐含的 this指针如下:
-
注意:我们不能显示的将形参
Data* const this
写出来,因为他是隐含的,我们不能抢了编译器的活。但是我们可以直接在类里面用。
2. this 指针的特性
①
this指针
的类型:类类型* const
,即成员函数中,不能给this指针赋值
。
② 只能在“成员函数”
的内部使用
③ this指针本质上是“成员函数”的形参
,当对象调用成员函数时,将对象地址> 作为实参传递给this形参。所以对象中不存储this指针。
④ this指针是“成员函数”第一个隐含的指针形参
,一般情况由编译器通过ecx寄存器自动传递,不需要用户传递。
注意:
指针的部分知识:
const 在*
之前,修饰指针指向的内容;
const 在*
之后,修饰指针本身;
3. this 指针在面试题中常见的考题
- ① this 指针存在哪里?
this
指针存在栈区
;
注意:
const
修饰的不一定是存在常量区的;
下图中,只有指针p
所指向的字符串才是存在常量区里面;
- 题目一:
① 成员函数
PrintA()
不在对象里面,所以不会解引用;
② 解引用的意思是到 p 所指向的空间去找,我要不要去找呢?
③PrintA()
的地址是在编译的时候确定的;
④PrintA()
不在p所指向的对象上面,所以不用对p
进行解引用
- 题目二:
-
因为这里解引用 this 指针,所以这里会运行崩溃; 原因:此程序崩溃是在
PrintA()
中,会隐含一个this->_a
,而this
指针是一个空指针,访问this指针_a的位置,_a
是成员变量,它是存在对象的空间里面的,所以_a
需要解引用,就要对空指针进行解引用,此时就会崩溃。
- 题目三:
PrintA()
没有存在对象里面,不需要解引用;
这里只需要传递this
指针;
编译器是否解引用,要观察解引用以后有没有意义,需不需要拿到这个对象,需不需要到这个对象的空间上面去找东西;
- 编译器有没有解引用,需要观察解引用之后有没有意义,
(*p)
不要被 这个*p
迷惑,PrintA()
这个没有存在对象里面,与这个p
无关,所以照样不会解引用!
p->
与*p
两者的性质是一样的,观察这句代码的反汇编之后的解释,发现一模一样!