[ C++ ] 一篇带你了解C++中隐藏的this指针

这篇具有很好参考价值的文章主要介绍了[ C++ ] 一篇带你了解C++中隐藏的this指针。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

本篇文章我们将一起讨论在有趣的知识点--隐藏的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指针

我们首先可以通过汇编来看看,d1,d2调用的函数是否相同。

[ C++ ] 一篇带你了解C++中隐藏的this指针

我们可以发现,最终打印的时候调用的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指针

[ C++ ] 一篇带你了解C++中隐藏的this指针

[ C++ ] 一篇带你了解C++中隐藏的this指针

 [ C++ ] 一篇带你了解C++中隐藏的this指针

注意:我们不能显示的写出来,因为他是隐含的,我们不能抢了编译器的活。但是我们可以直接在类里面用。

2.this指针的特性

在真正的编译器中this指针的用const修饰的,this指针本身是不能被修改的,但是内容是可以修改的。并且我们是可以使用的

[ C++ ] 一篇带你了解C++中隐藏的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;
}

运行结果: 

[ C++ ] 一篇带你了解C++中隐藏的this指针

 并且我们还能这样写,但是我们不能显示的写出Date* this。

[ C++ ] 一篇带你了解C++中隐藏的this指针

 文章来源地址https://www.toymoban.com/news/detail-471445.html

我们接下来再看看this指针是不能修改的,大家看下面这个能过吗?答案肯定是不能的,因为this是被const修饰的,不能修改this指针的。

[ C++ ] 一篇带你了解C++中隐藏的this指针

我们会发现 编译器也会报错:error C2106: “=”: 左操作数必须为左值

[ C++ ] 一篇带你了解C++中隐藏的this指针

 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指针被初始化为空指针。这是允许的。[ C++ ] 一篇带你了解C++中隐藏的this指针

 [ C++ ] 一篇带你了解C++中隐藏的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的位置,就要对空指针进行解引用,此时就会崩溃。我们也可通过调试观察到。

[ C++ ] 一篇带你了解C++中隐藏的this指针

[ C++ ] 一篇带你了解C++中隐藏的this指针

 (3)this指针是存在哪里的?

a.栈  b.堆  c.静态区  d.常量区

答案:a

解释:this指针是个形参,形参是在函数的栈桢里,在函数的栈桢里面的变量是属于栈中的。

有时编译器会使用寄存器对其进行优化,this指针会存在寄存器中。

[ C++ ] 一篇带你了解C++中隐藏的this指针

 [ C++ ] 一篇带你了解C++中隐藏的this指针

 

(本篇完)

 

到了这里,关于[ C++ ] 一篇带你了解C++中隐藏的this指针的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • [Linux 基础] 一篇带你了解linux权限问题

    Linux下有两种用户:超级用户(root)、普通用户。 超级用户:可以再linux系统下做任何事情,不受限制 普通用户:在linux下做有限的事情。 超级用户的命令提示符是“#”,普通用户的命令提示符是“ $ ” 命令: su [用户名] 功能: 切换用户。 例如,要从root用户切换到普通用

    2024年02月08日
    浏览(19)
  • 【Mysql】一篇带你了解数据定义,操作和查询语言

    目录 数据定义语言DDL(Data Definition Language) 一.对数据库的操作 二.对数据表的操作 数据操作语言DML(Data Manipulation Language) 一.添加 insert into 二.删除  delete 三.修改  update 数据查询语言DQL(Data Query Language) 一.查询 select 二. 1.between ... and ...(在....之间) 2.in, exists

    2024年02月12日
    浏览(32)
  • [数据结构 -- 手撕排序第二篇] 一篇带你详细了解希尔排序

    目录 1、常见排序算法 1.1 插入排序基本思想 2、希尔排序 2.1 希尔排序( 缩小增量排序 ) 2.1.1 预排序阶段 2.1.2 插入排序阶段 2.2 单趟希尔排序 2.2.1 思路分析 2.2.2 代码实现 3、希尔排序代码实现 4、希尔排序时间复杂度 5、希尔排序与插入排序效率对比 6、希尔排序特性总结 直接

    2024年02月13日
    浏览(22)
  • 【C语言】-- 一篇带你了解C语言内存五大区——栈区,堆区,全局区,常量区,代码区

    目录 1 C语言的内存分区 1.1 内存五大分区 1.2 内存分区简介 1.2.1 栈区(stack) 1.2.2 堆区(heap) 1.2.3 (全局)静态区 1.2.4 常量区 1.2.5 代码区 创作不易,如果本篇博客对您有一定的帮助,大家记得留言+点赞哦。 C语言已经持续学习一段时间了,今天特此总结一下关于C语言内存的五大区

    2024年02月16日
    浏览(23)
  • 数组(一篇带你掌握数组)

        在之前,我们想要存储一个数据的时候可以创建变量,例如存储一个整形的变量,我们使用int类型的变量来存储,那么如果存储一组相同类型的数据呢?这时我们就引入了 数组 的概念。 目录 一、一维数组的创建和初始化 1.1数组的创建 1.2 数组的初始化 1.3 一维数组的使

    2023年04月08日
    浏览(24)
  • 一篇带你精通MPLS

    MPLS:多协议标签交换 可以基于多种不同的3层协议来生成2.5层的标签信息 包为网络层的PDU,故包交换就是基于IP地址进行数据转发;也就是路由器的路由行为。(路由器和终端基于3层的IP地址数据转发的路由行为) 原始包交换 查两张表 在包交换过程中,数据包每经过一个路

    2024年02月22日
    浏览(25)
  • Javaの一篇带你吃透接口

    随着接口的到来,JavaSE的学习笔记大结局也即将来临,最近的几篇博客写到了封装,继承,多态,抽象类等等,都循序渐进得介绍了这类的知识,大家如果接口这一块理解的很困难的话,建议去完善一下前面的知识哦 👉Java封装 👉静态成员 👉代码块 👉内部类 👉继承 👉多

    2023年04月08日
    浏览(26)
  • 【数据结构】一篇带你彻底吃透 顺序表

    顺序表是用一段物理地址连续的存储单元依次存储数据元素的线性结构,一般情况下采用数组存储。在数组上完成数据的增删查改等功能。 顺序表一般可以分为: 静态顺序表:使用定长数组存储元素。 动态顺序表:使用动态开辟的数组存储。 而现实的顺序表大多数采用动态

    2023年04月19日
    浏览(40)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包