本篇文章我们将一起讨论在有趣的知识点--隐藏的this指针。本篇我们要使用到之前我们所学习到的C++类与对象(1),如果有各位小伙伴还不曾了解类与对象的简单思想,可以访问上篇博客:[ C++ ] 带你一篇了解什么是OOP(面向对象编程),什么是封装? -- 类与对象(上)
目录
1.this指针的引出
2.this指针的特性
3.练习一下
在之后的学习中,我们将认识一个新的类:日期类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;
}![[ C++ ] 一篇带你了解C++中隐藏的this指针_c++](https://file.cfanz.cn/uploads/gif/2021/09/18/17/58Y87YaF16.gif)
输出结果:
![[ C++ ] 一篇带你了解C++中隐藏的this指针_编译器_02](https://file.cfanz.cn/uploads/png/2022/05/15/11/3Fa84J827M.png)
![[ C++ ] 一篇带你了解C++中隐藏的this指针_this指针_03](https://file.cfanz.cn/uploads/gif/2021/09/18/17/58Y87YaF16.gif)
我们首先可以通过汇编来看看,d1,d2调用的函数是否相同。
![[ C++ ] 一篇带你了解C++中隐藏的this指针_c++_04](https://file.cfanz.cn/uploads/png/2022/05/15/11/5Za1WbAN24.png)
![[ C++ ] 一篇带你了解C++中隐藏的this指针_c++_05](https://file.cfanz.cn/uploads/gif/2021/09/18/17/58Y87YaF16.gif)
我们可以发现,最终打印的时候调用的Display()是同一个函数, 那么既然d1,d2调用的都是同一个函数,编译器如何知道d1是2022-5-11,d2是2022-5-12呢?Display()都访问的_year,_month,_day。而且去公共代码区访问的Display(),这是为什么呢?
这是因为C++在这段代码中做出手脚,C++在这里增加了一个this指针,这里是因为Display会增加一个this形参。C++编译器给每个“非静态的成员函数“增加了一个隐藏的指针参数,让该指针指向当前对象(函数运行时调用该函数的对象),在函数体中所有成员变量的操作,都是通过该指针去访问。只不过所有的操作对用户是透明的,即用户不需要来传递,编译器自动完成。
在调用的时候也传的是各自的地址。这样就十分清晰明了了。这就是隐含的this指针
![[ C++ ] 一篇带你了解C++中隐藏的this指针_编译器_06](https://file.cfanz.cn/uploads/png/2022/05/15/11/Q10Y5X6DdN.png)
编辑
![[ C++ ] 一篇带你了解C++中隐藏的this指针_编译器_08](https://file.cfanz.cn/uploads/png/2022/05/15/11/0J6CdKd0O1.png)
![[ C++ ] 一篇带你了解C++中隐藏的this指针_编译器_09](https://file.cfanz.cn/uploads/gif/2021/09/18/17/58Y87YaF16.gif)
![[ C++ ] 一篇带你了解C++中隐藏的this指针_编译器_10](https://file.cfanz.cn/uploads/png/2022/05/15/11/IW6293E1S9.png)
![[ C++ ] 一篇带你了解C++中隐藏的this指针_c++_11](https://file.cfanz.cn/uploads/gif/2021/09/18/17/58Y87YaF16.gif)
![[ C++ ] 一篇带你了解C++中隐藏的this指针_c++_12](https://file.cfanz.cn/uploads/png/2022/05/15/11/7d14166d50.png)
![[ C++ ] 一篇带你了解C++中隐藏的this指针_c++_13](https://file.cfanz.cn/uploads/gif/2021/09/18/17/58Y87YaF16.gif)
注意:我们不能显示的写出来,因为他是隐含的,我们不能抢了编译器的活。但是我们可以直接在类里面用。
2.this指针的特性
在真正的编译器中this指针的用const修饰的,this指针本身是不能被修改的,但是内容是可以修改的。并且我们是可以使用的
![[ C++ ] 一篇带你了解C++中隐藏的this指针_this指针_14](https://file.cfanz.cn/uploads/png/2022/05/15/11/28b5R27V21.png)
![[ C++ ] 一篇带你了解C++中隐藏的this指针_编译器_15](https://file.cfanz.cn/uploads/gif/2021/09/18/17/58Y87YaF16.gif)
我们可以在类中打印一下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;
}![[ C++ ] 一篇带你了解C++中隐藏的this指针_c++_16](https://file.cfanz.cn/uploads/gif/2021/09/18/17/58Y87YaF16.gif)
运行结果:
![[ C++ ] 一篇带你了解C++中隐藏的this指针_this指针_17](https://file.cfanz.cn/uploads/png/2022/05/15/11/Wc6J16e636.png)
![[ C++ ] 一篇带你了解C++中隐藏的this指针_this指针_18](https://file.cfanz.cn/uploads/gif/2021/09/18/17/58Y87YaF16.gif)
并且我们还能这样写,但是我们不能显示的写出Date* this。
![[ C++ ] 一篇带你了解C++中隐藏的this指针_c++_19](https://file.cfanz.cn/uploads/png/2022/05/15/11/e54175X60M.png)
![[ C++ ] 一篇带你了解C++中隐藏的this指针_编译器_20](https://file.cfanz.cn/uploads/gif/2021/09/18/17/58Y87YaF16.gif)
我们接下来再看看this指针是不能修改的,大家看下面这个能过吗?答案肯定是不能的,因为this是被const修饰的,不能修改this指针的。
![[ C++ ] 一篇带你了解C++中隐藏的this指针_编译器_21](https://file.cfanz.cn/uploads/png/2022/05/15/11/bff5W23ffd.png)
![[ C++ ] 一篇带你了解C++中隐藏的this指针_c++_22](https://file.cfanz.cn/uploads/gif/2021/09/18/17/58Y87YaF16.gif)
我们会发现 编译器也会报错:error C2106: “=”: 左操作数必须为左值
![[ C++ ] 一篇带你了解C++中隐藏的this指针_this指针_23](https://file.cfanz.cn/uploads/png/2022/05/15/11/V555aNd795.png)
![[ C++ ] 一篇带你了解C++中隐藏的this指针_c++_24](https://file.cfanz.cn/uploads/gif/2021/09/18/17/58Y87YaF16.gif)
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++ ] 一篇带你了解C++中隐藏的this指针_编译器_25](https://file.cfanz.cn/uploads/gif/2021/09/18/17/58Y87YaF16.gif)
结果:C
原因:Show()函数是存在公共代码区中,编译的时候在公共代码区中找到这个函数,和普通的函数调用是一样的,只需要call函数地址就行。我们发现这里p是空指针,传过去的this指针只是接收了p的空指针,就类似于this指针被初始化为空指针。这是允许的。![[ C++ ] 一篇带你了解C++中隐藏的this指针_this指针_26](https://file.cfanz.cn/uploads/png/2022/05/15/11/efbccc7712.png)
![[ C++ ] 一篇带你了解C++中隐藏的this指针_编译器_27](https://file.cfanz.cn/uploads/gif/2021/09/18/17/58Y87YaF16.gif)
![[ C++ ] 一篇带你了解C++中隐藏的this指针_c++_28](https://file.cfanz.cn/uploads/png/2022/05/15/11/R691KT0613.png)
![[ C++ ] 一篇带你了解C++中隐藏的this指针_c++_29](https://file.cfanz.cn/uploads/gif/2021/09/18/17/58Y87YaF16.gif)
(2)下面的程序的运行结果是? A.编译报错 B.运行崩溃 C.正常运行
class B
{
public:
void PrintA()
{
cout << _a << endl;
}
private:
int _a;
};
int main()
{
B* p2 = nullptr;
p2->PrintA();
return 0;
}![[ C++ ] 一篇带你了解C++中隐藏的this指针_c++_30](https://file.cfanz.cn/uploads/gif/2021/09/18/17/58Y87YaF16.gif)
结果:B
原因:此程序崩溃是在PrintA()中,会隐含一个this->_a,而this指针是一个空指针,访问this指针_a的位置,就要对空指针进行解引用,此时就会崩溃。我们也可通过调试观察到。
![[ C++ ] 一篇带你了解C++中隐藏的this指针_编译器_31](https://file.cfanz.cn/uploads/png/2022/05/15/11/O7c8b8MSb2.png)
![[ C++ ] 一篇带你了解C++中隐藏的this指针_this指针_32](https://file.cfanz.cn/uploads/gif/2021/09/18/17/58Y87YaF16.gif)
![[ C++ ] 一篇带你了解C++中隐藏的this指针_编译器_33](https://file.cfanz.cn/uploads/png/2022/05/15/11/1850H915P3.png)
![[ C++ ] 一篇带你了解C++中隐藏的this指针_this指针_34](https://file.cfanz.cn/uploads/gif/2021/09/18/17/58Y87YaF16.gif)
(3)this指针是存在哪里的?
a.栈 b.堆 c.静态区 d.常量区
答案:a
解释:this指针是个形参,形参是在函数的栈桢里,在函数的栈桢里面的变量是属于栈中的。
有时编译器会使用寄存器对其进行优化,this指针会存在寄存器中。
![[ C++ ] 一篇带你了解C++中隐藏的this指针_c++_35](https://file.cfanz.cn/uploads/png/2022/05/15/11/768382Sd7P.png)
![[ C++ ] 一篇带你了解C++中隐藏的this指针_this指针_36](https://file.cfanz.cn/uploads/gif/2021/09/18/17/58Y87YaF16.gif)
![[ C++ ] 一篇带你了解C++中隐藏的this指针_c++_37](https://file.cfanz.cn/uploads/png/2022/05/15/11/65eZ8BK11Y.png)
![[ C++ ] 一篇带你了解C++中隐藏的this指针_this指针_38](https://file.cfanz.cn/uploads/gif/2021/09/18/17/58Y87YaF16.gif)
(本篇完)










