C++深入浅出讲解隐藏this指针的用法

目录
  • 1.this指针的引出
  • 2.this指针的特性
  • 3.练习一下

本篇文章我们将一起讨论在有趣的知识点--隐藏的this指针。本篇我们要使用到之前我们所学习到的C++类与对象,如果有各位小伙伴还不曾了解类与对象的简单思想,可以访问上篇:

在之后的学习中,我们将认识一个新的类:日期类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;
}

输出结果:

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

我们可以发现,最终打印的时候调用的Display()是同一个函数,那么既然d1,d2调用的都是同一个函数,编译器如何知道d1是2022-5-11,d2是2022-5-12呢?Display()都访问的_year,_month,_day。而且去公共代码区访问的Display(),这是为什么呢?

这是因为C++在这段代码中做出手脚,C++在这里增加了一个this指针,这里是因为Display会增加一个this形参。C++编译器给每个“非静态的成员函数“增加了一个隐藏的指针参数,让该指针指向当前对象(函数运行时调用该函数的对象),在函数体中所有成员变量的操作,都是通过该指针去访问。只不过所有的操作对用户是透明的,即用户不需要来传递,编译器自动完成。

在调用的时候也传的是各自的地址。这样就十分清晰明了了。这就是隐含的this指针

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

2.this指针的特性

在真正的编译器中this指针的用const修饰的,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;
}

运行结果:

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

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

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

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指针被初始化为空指针。这是允许的。

(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的位置,就要对空指针进行解引用,此时就会崩溃。我们也可通过调试观察到。

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

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

答案:a

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

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

到此这篇关于C++深入浅出讲解隐藏this指针的用法的文章就介绍到这了,更多相关C++this指针内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • C++函数指针+对象指针+this指针+指向类静态和非静态成员的指针

    目录 1.指向函数的指针 2.对象指针 3.this指针 4.指向类的非静态成员的指针 5.指向类的静态成员的指针 1.指向函数的指针 函数的代码在内存中的首地址,是由函数名表示的,也就是说函数名等价于函数代码首地址.因此,可以定义一个指向函数的指针,即函数指针.函数指针定义和赋值的语法如下,其中数据类型代表指向函数的返回类型,形参表为指向函数的形参表:赋值时必须保证指向的函数名和函数指针的返回类型和形参完全相同: 数据类型 (*函数指针名)(形参表);函数指针名 = 函数名; 下面的例子定义了

  • C++this指针详情

    还是Stock股票这个类,假设我们要实现一个方法,比较一下当前股票和传入的股票, 返回价格高的那个股票.在我们实现的时候,会遇到一点问题. const Stock & Stock::topVal(const Stock &s) const {     if (s.total_val > total_val) {         return s;     }else {         return ????;     } } 这段代码当中有一些问题,我们一个一个来说. 首先说函数签

  • 一起来学习C++中类的this指针以使用

    目录 一,this指针的注意点 错误用例: 二,this指针存在哪里 三,this指针的面试坑题 总结 c++的类中,非静态的成员函数都有一个隐藏的this指针,在函数体中所以的成员变量都是通过this指针来访问的.但是this指针是对用户是透明的,用户不需要显示的给this指针传参,编译时会自动接收参数. 一,this指针的注意点 调用成员函数时,不可以显示给this指针传参 定义成员函数时,不能显示的声明this指针 在成员函数内部,可以显示的使用this指针 用一个日期类,来讲述this指

  • C++深入探究类与对象之对象模型与this指针使用方法

    目录 C++对象模型和this指针 1 成员变量和成员函数分开存储 2 this指针概念 3 空指针访问成员函数 4 const修饰成员函数 C++面向对象的三大特性为:封装.继承.多态 C++认为万事万物都皆为对象,对象上有其属性和行为 例如: ​ 人可以作为对象,属性有姓名.年龄.身高.体重…,行为有走.跑.跳.吃饭.唱歌… ​ 车也可以作为对象,属性有轮胎.方向盘.车灯…,行为有载人.放音乐.放空调… ​ 具有相同性质的对象,我们可以抽象称为类,人属于人类,车属于车类 C++对象模型和th

  • C++ this指针和空指针的具体使用

    每一个非静态成员函数只会诞生一份函数实例,也就是说多个同类型的对象会共用一块代码那么问题是:这-块代码是如何区分那个对象调用自己的呢? C++通过提供特殊的对象指针,this指针,解决上述问题.this指针指向被调用的成员函数所属的对象 this指针是隐含每一个非静态成员函数内的-种指针 this指针不需要定义,直接使用即可 this指针的用途: 当形参和成员变量同名时,可用this指针来区分 在类的非静态成员函数中返回对象本身,可使用return this 一.this指针 1 this指针解

  • C++ 中this指针的用途详解

    目录 1.区分形参和变量同名时: 2.return *this返回函数本身 总结 先说结论: 1.形参和变量同名时,可用this指针来区分 2.在类的非静态成员函数中返回本身,可用return *this 1.区分形参和变量同名时: #include <iostream> using namespace std; class Person { public: Person(int age) { age = age; } int age; }; void test01() { Person p1

  • 带你了解C++this指针的用法及其深究

    目录 前言 一.this指针是个什么东东,重要吗? 二.案例理解 主要的用途 总结 前言 今天,码神像一个新车手一样,尝试着用模板来更新一下,不要建议哦,毕竟没有放弃爱情的拓海也不是真正的车神,哈哈,发车了 一.this指针是个什么东东,重要吗? 首先,我以码神的名义起誓,this指针绝对重要,尤其是对于c++这个面向对象编程的语言来说! 有的码手可能要说了:你说重要就重要?那我还说不重要呢? 这个么,空口无凭,我现在来举一个例子: 我们知道对于一个类来说,要有很多工作要做,其中类的成员函数可以

  • C++对象模型和this指针详解

    目录 对象模型 一. 二. 三. 四. 五. this指针 一. 二. 总结 对象模型 成员变量和成员函数分开存储 一. 只有非静态成员变量才属于类的对象上 空对象占用字节为1 class Person { }; void test01() { Person p; cout << "size of = " << sizeof(p) << endl; } int main() { test01(); system("pause");

  • C++静态成员函数和this指针详解

    目录 静态成员 1.静态成员变量 2.静态成员函数 成员变量和成员函数分开存储 this 指针 空指针访问成员函数 总结 静态成员 静态成员就是在成员变量和成员函数前加上关键字static,称为静态成员 静态成员分为: 1.静态成员变量 所有对象共享同一份数据 在编译阶段分配内存 类内声明,类外初始化 示例: #include<iostream> using namespace std; class Person { public: static int m; // 所有对象共享同一份数据 }

  • C++深入浅出讲解隐藏this指针的用法

    目录 1.this指针的引出 2.this指针的特性 3.练习一下 本篇文章我们将一起讨论在有趣的知识点--隐藏的this指针.本篇我们要使用到之前我们所学习到的C++类与对象,如果有各位小伙伴还不曾了解类与对象的简单思想,可以访问上篇: 在之后的学习中,我们将认识一个新的类:日期类Date.正如我们所想的那样,传入一个日期,我们可以输出我们所输入的日期. 1.this指针的引出 那我们首先来看一下,这段代码会输出什么结果呢? class Date { public: void Display(

  • C语言 深入浅出讲解指针的使用

    目录 一.利用指针倒序字符串 二.题目实例 三.总结 一.利用指针倒序字符串 void _reversal(char* left, char* right) { while (left < right) { char tmp = *left; *left = *right; *right = tmp; left++; right--; } } 通过上述代码不难看出,left与right分别代表一个字符数组的首端和尾端,通过中间变量 tmp进行首尾交换,left++中的left是char*类型,同

  • C#中this指针的用法示例

    本文实例展示了C#中this指针的用法,对于初学者进一步牢固掌握C#有很大帮助,具体内容如下: 一.this指针是什么: 这里有一些面向对象编程的概念需要说明:类(Class)的概念和对象(Object)的概念 类是对事物概括,也是C#编码时所有代码归属的基本单位:而对象是对类的实例化,也就是C#里new方法的返回值.写代码是不能直接用操作类,而只能先实例化类,然后我们用这个类被实例化后的对象. 通俗一些的说明是,"类"好比是"人"的概念,而我们把类实例化后,就成为

  • 深入浅出讲解Java集合之Collection接口

    目录 一.集合框架的概述 二.集合框架(Java集合可分为Collection 和 Map 两种体系) 三.Collection接口中的方法的使用 四.集合元素的遍历操作 A. 使用(迭代器)Iterator接口 B. jdk5.0新增foreach循环,用于遍历集合.数组 五.Collection子接口之一:List接口 List接口方法 ArrayList的源码分析: JDK 7情况下: JDK 8中ArrayList的变化: LinkedList的源码分析: Vector的源码分析: 六.

  • 深入浅出讲解Java集合之Map接口

    目录 一.Map接口继承树 二.Map接口中的常用方法 三.源码分析 1. HashMap的底层实现原理? 2.LinkedHashMap的底层实现原理(了解) 四.Collections工具类 一.Map接口继承树 Map:双列数据,存储key-value对的数据 ---类似于高中的函数:y = f(x) A.HashMap:作为Map的主要实现类:线程不安全的,效率高:存储null的key和value a.LinkedHashMap:保证在遍历map元素时,可以按照添加的顺序实现遍历. 原因

  • Java超详细讲解接口的实现与用法

    目录 1.接口的定义 2.接口的实现 3.接口的引用 4.接口的继承 5.利用接口实现多重继承 1.接口的定义 接口是一种特殊的抽象类,是Java提供的一个重要的功能,与抽象类不同的是: 接口的所有数据成员都是静态的且必须初始化. 接口中的所有方法必须都是抽象方法,不能有一般的方法. [public] interface 接口名称 [extends  父接口名列表]{    [public] [static] [final]数据类型 成员变量名 = 常量;    ...    [public][

  • C++超详细讲解隐藏私有属性和方法的两种实现方式

    目录 例子 用抽象类解决问题 用Pimpl风格解决问题 总结 参考 在我们编写程序的时候,会将程序模块化,常见的就是用动态链接库的方式,然后导出函数接口或者类.而对于导出类的方式,作为模块的实现者,不论是给第三方使用或者自己的项目使用,应该都不太愿意暴露自己的私有属性和方法,个人碰到的主要有以下两个常见原因: 通过隐藏私有属性和方法,让被调用者猜不到其实现方式 私有方法中或者属性中,可能会存在一些第三方的头文件或者库的依赖,而对于被调用方来说不应该直接依赖 本文将介绍两种方式来满足以上的需求,一

  • C++深入浅出讲解内存四区与new关键字的使用

    目录 写在前面 内存四区 程序运行前 代码区 全局区 程序运行后 栈区 堆区 new关键字 new的基本语法 利用new开辟数组 写在前面 从本文开始我就要日常更新C++入门博文啦,从核心编程开始,之前的一些基础我就不再从零整理了,只有函数传参.结构体.指针.数组等稍微难理解的知识在之前的博文写的比较全面:因为竞争确实很大,其他人总结的也很好,要看更详细的基础就看本站的技能树,非常全面:我写博客的初衷一是可以记录自己的学习,加以巩固:二是给更多的人更容易的讲解来快速入门C++,C/C++永不过时

  • C语言超详细讲解宏与指针的使用

    目录 1.关于define 2.初识指针 (1)内存 (2)示例 (3)指针的使用示例 (4)指针变量的大小 1.关于define define是一个预处理指令,有两种用法,一种是用define定义常量:另外一种是define定义宏. 下面的例子为利用define定义常量 #define _CRT_SECURE_NO_WARNINGS #define MAX 1000 #include <stdio.h> int main() { printf("%d\n",MAX); r

  • C++深入浅出讲解缺省参数

    目录 缺省参数 定义 用法 缺省参数 一般情况下,函数调用时的实参个数应与形参相同,但为了更方便地使用函数,C++也允许定义具有缺省参数的函数,这种函数调用时,实参个数可以与形参不相同. 定义 缺省参数指在定义函数时为形参指定缺省值(默认值).这样的函数在调用时,对于缺省参数,可以给出实参值,也可以不给出参数值.如果给出实参,将实参传递给形参进行调用,如果不给出实参,则按缺省值进行调用. 缺省参数的函数调用:缺省实参并不一定是常量表达式,可以是任意表达式,甚至可以通过函数调用给出.如果缺省实参是

随机推荐