【C++】this指针讲解超详细!!!

在这里插入图片描述


个人主页 :阿然成长日记 点击可跳转
个人专栏: 数据结构与算法C语言进阶
不能则学,不知则问,耻于问人,决无长进

文章目录

  • 一、this指针引入
    • 1.引入
    • 2.分析
    • 3.图示
  • 二、 this指针存在哪里?
  • 三、this指针的特性
  • 四、 案例分析

一、this指针引入

1.引入

#include
using namespace std;
class Data
{
public:
	void Init(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()
{
//创建Data的对象1
	Data d1;
	d1.Init(1999, 1, 1);
//创建Data的对象2
	Data d2;
	d2.Init(2023, 1, 1);
//调用print函数
	d1.print();
	d2.print();
	return 0;
}

打印结果:
【C++】this指针讲解超详细!!!_第1张图片

2.分析

上面代码运行结果中,为什么两个对象调用同一个函数能打印出不同的日期呢?或者说同一个函数如何做到结果不同呢?
简单说是通过C++的一个关键字this来实现的。
上面代码着编译后,就成了如下:

#include
using namespace std;
class Data
{
public:
	void Init(int year,int month,int day)
	{
		_year = year;
		_month = month;
		_day = day;
	}
	void print(Data* this)
	{
		cout << this->_year << ":" << this->_month << ":" << this->_day << endl;
	}
private:
	int _year;
	int _month;
	int _day;
};

int main()
{
//创建Data的对象1
	Data d1;
	d1.Init(1999, 1, 1);
//创建Data的对象2
	Data d2;
	d2.Init(2023, 1, 1);
//调用print函数
	d1.print(&d1);
	d2.print(&d2);
	return 0;
}

当不同对象调用print函数时,其实在底层是传了一个Data*类型的指针this。

void print(Data* this)
	{
		cout << this->_year << ":" << this->_month << ":" << this->_day << endl;
	}

> 如下图所示:
其实底层还是和C语言函数调用一样,也需要传参,只不过C++的编译器为我们默默做了这些事情,让我们用起来更方便。但是,不能显示的去写出this的相关实参和形参,需要注意的是在类中可以使用this->。

3.图示

【C++】this指针讲解超详细!!!_第2张图片

this本质是一个形参,哪个对象调用他,就指向哪个对象。

二、 this指针存在哪里?

下图是代码在vs2019编译器下执行的汇编语句
【C++】this指针讲解超详细!!!_第3张图片
当执行d1.Init(1999, 1, 1);时,先是将三个实参进行压栈。其实实参应该有4个,还有一个隐藏的this指针
(1)000426EF push 1
(2)000426F1 push 1
(2)000426F3 push 7CFh
通过这一句(4)000426F8 lea ecx,[d1] 我们可以清晰的看到this指针在vs编译器下,是存到了寄存器( ecx)。
其实,this指针存在的位置一般是在栈帧上,不同的编译器有所不同,例如vs2019就是存在寄存器上。
因为this指针,占用内存小并且需要频繁使用,所以,将它放到寄存器里能大大提升运行效率。

三、this指针的特性

  1. this指针的类型:类类型* const,即成员函数中,不能给this指针赋值。
  2. 只能在“成员函数”的内部使用
  3. this指针本质上是“成员函数”的形参,当对象调用成员函数时,将对象地址作为实参传递给
    this形参。所以对象中不存储this指针。
  4. this指针是“成员函数”第一个隐含的指针形参,一般情况由编译器通过ecx寄存器自动传
    递,不需要用户传递

四、 案例分析

下面代码会出现问题吗?

class A
{
public:
void Print()
{
cout << "Print()" << endl;
}
private:
int _a;
};
int main()
{
A* p = nullptr;
p->Print();
return 0;
}

前提知识

  • p的意义有两个。1.p是A类一个对象的指针,p->print(),对象的指针调用函数肯定是找成员函数中的,也就是说编译的时候检查语法,让我们知道print函数是A类中的成员函数,起到定位语法作用。

  • p指针为空,相当于this指针为空。

  • 成员变量存储在对象中

  • 成员函数没有存储在对象中

  • p->Print();说明调用的是A类中的成员函数

调用print函数与this指针无关,只有访问成员变量时才会使用到this。
因为函数是在编译链接的时候找的(本质是找函数的地址),上一篇详细讲过对象的存储方式中讲过,成员函数存在公共区域的函数表(函数表中存有成员函数的地址)查找修饰后的函数名【因为C++支持重载,所以需要对函数名 进行特殊的修饰】来进行查找。

所以,代码运行正常。
看下面代码:

class A
{
public:
void PrintA()
{
cout<<_a<<endl;
}
private:
int _a;
};
int main()
{
A* p = nullptr;
p->PrintA();
return 0;
}

printA函数中使用了成员变量,编译时printA函数底层如下形式:

void PrintA(Data* this)
{
cout<<this_a<<endl;
}
mian函数中是
p->PrintA(p);

将p传给了this指针。
_a=>this_a,需要访问this指针,但此时this指针为空。
所以,运行崩溃!

你可能感兴趣的:(C++基础,c++,开发语言)