1.this指针的引入
首先我们看下面这一段代码
class Date
{
public:
void DateSet(int year, int month, int day)
{
_year = year;
_month = month;
_day = day;
}
void print()
{
cout << _year << "-" << _month << "-" << _day << endl;
}
private:
int _year;
int _month;
int _day;
};
int main()
{
Date d1;
d1.DateSet(2022, 12, 9);
d1.print();
Date d2;
d2.DateSet(2002, 3, 8);
d2.print();
return 0;
}
对于刚开始学习c++的同学来说,你肯定会有这样的疑惑,为什么d1调用prinf()函数和d2调用print()函数的结果是这样的?prinf()这个函数也没有参数呀,为什么d1,d2分别调用printf()函数结果会不同呢。调用一个无参的函数,结果应该都是一样的呀。
其实是这样的,成员函数print()并不是真正的无参函数,其实有一个隐藏的参数this指针,我们调用的时候也并不是真的没有传参,而是d1调用的时候就把&d1传给了this,d2调用的时候把&d2传给了this。
2.this指针的特性
- this指针存在于类的每个非静态成员函数。
- this指针具有const属性
- this指针只能在成员函数的内部使用
- this指针是一个形参,对象中并不存储this指针
3.关于this指针的面试题
-
this指针存在哪里?
this指针本质上是一个形参,我们知道函数调用会建立栈帧,而在这之前需要先将形参入栈,所以形参应该在栈上。
此外,有些编译器会优化,可能直接把this指针放到寄存器里面了。因为寄存器的速度比内存快很多,对于这种比较小的且频繁使用指针,直接放在寄存器是很合适的。
-
this指针可以为空吗?
首先nullptr是什么呢?以32位为例,进程虚拟地址空间的大小是4G个字节,从0x00000000到0xFFFFFFFF共2^32个字节(即4G)。nullptr就是0x00000000的地址,nullptr = (void*)0;这个地址不能用来存放数据,所以当我们写类似下面这种代码的时候会报错
int* p = nullptr;//这里其实发生了隐式类型转换,nullptr原本是void*类型,转换成了int* *p = 10;//不让存放数据的地方你偏要放数据,非法访问。
this指针是一个形参,不就是一个变量吗,你创建一个变量给他赋值0x00000000可不可以,肯定是可以的呀,但是访问就不行了。比如下面这段代码
class A { public: void PrintA() { cout << _a << endl; } void Show() { cout << "Show()" << endl; } private: int _a; }; int main() { A* p = nullptr; p->Show();//这句代码会不会报错?不会,show是成员函数,成员函数放在公共的代码区,这里只是调用成员函数,该函数只是打印一句话,并没有非法访问。 p->PrintA();//这句就会报错了,虽然也是调用成员函数,但是printA()函数里面访问了成员变量,这就属于非法访问了 }