This 指针详解(C++版)

文章目录


前言

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, 4, 13);
	d2.SetDate(2022, 4, 14);
	d1.Display();
	d2.Display();
	return 0;
}

关于以上的代码,不知大家是否会有这样的一个疑问??

代码本身而言:

d1.Display()和d2.Display()可以很清晰观察到其函数调用的对象!!!

函数本身而言:

Date类中的两个成员函数,其函数体中没有任何关于对象的信息,那么在调用函数时,函数是如何辨别是设置d1对象,还是d2对象呢???

那么C++上,我们无法理解,咱们可以C语言的代码上进行对比

typedef struct Date
{
	int _year;
	int _month;
	int _day;
}Date;
void Display(Date* d)
{
	printf("%d-%d-%d\n", d->_year, d->_month, d->_day);
}
void SetDate(Date* d, int year, int month, int day)
{
	d->_year = year;
	d->_month = month;
	d->_day = day;
}
int main()
{
	Date d1,d2;
	SetDate(&d1, 2022, 4, 13);
	SetDate(&d2, 2022, 4, 14);
	Display(&d1);
	Display(&d2);
	return 0;
}

细心的铁铁们,就可以发现在两段代码对比,其实就差了一个指针!!!

那么C++这段代码就真的没有指针了吗?

实则,C++是通过引入this指针来解决该问题的!!!

一、this指针定义

C++编译器给每个“非静态的成员函数”增加了一个隐藏的指针参数,让该指针指向当前对象(函数运行时调用该函数的对象)在该函数体所有成员变量的操作,都是通过该指针去访问,只不过所有的操作对于用户是透明,即用户不需要来传递编译器自动完成

将this指针添加上去,也仍为正确!(注:但不能在形参列表中添加

二、 this指针的特征

 1.this指针的类型,类类型 * const(如图一日期类中,当前this类型则为Date * const),其实也表明了this的指向是不可修改的

2.this指针本质上是一个成员函数的形参,是对象调用成员函数时,将对象地址传参给this指针这一形参,故对象中不存储this指针

3.this指针是成员函数第一个隐含的指针形参,一般情况下由编译器通过寄存器自动传递(环境为===VS 2019版本),不需用客户传递

 由调试以及反汇编代码可以清晰的观察到

 该条指令则是获取的this形参指针存于ecx寄存器中

 

 以成员变量_year赋值为例,编译器先从寄存器获取this指针后,在通过this指针对成员变量_year,进行赋值操作

(由此也可得出this的隐含指针形参特点,以及存储于寄存器,编译器由该指针对成员变量进行操作的特征)

补:并不是所有的this指针都是由寄存器自动传递的

成员函数: void TextFunction(...);

 由push指令可知,该类this指针形参是通过参数压栈的方式传递的

 那么如何该判断判断this指针是通过ecx寄存器传递还是通过参数压栈的方式进行传递的呢?

两者差别主要在于调用约定不同

SetDate()成员函数采用的__thiscall,TextFunc()成员函数则采用的是__cdecl

三、this指针面试题

1.this指针存在哪里?

如图Address()成员函数的栈帧,esp,ebp为分别标记栈顶和栈底的两个寄存器,在VS2019监视窗口中,通过引用&rthis地址实则就为&this地址,从范围大小,可清晰发现this指针存储于栈当中

 2.this指针可以为空吗?

class Date
{
   public :
	   void SetDate(int year,int month,int day)
	   {
		   _year = year;
		   _month = month;
		   _day = day;
	   }
	   void TextFunc()
	   {
		   cout << "Date::TextFunc()" << endl;
	   }
	   void Print()
	   {
		   cout << this << endl;
	   }
   private:
	   int _year;
	   int _month;
	   int _day;
};
int main()
{
	Date d1;
	d1.SetDate(2022, 4, 17);
	d1.Print();
    //this指针实则为当前对象(d1)的地址,用date局部变量接收
	Date* date = &d1;
	date = nullptr;
   	date->Print();
	date->TextFunc();
	return 0;
}

能完成编译!!!

但是发现经过下列一点变动

int main()
{
	Date d1;
	d1.SetDate(2022, 4, 17);
	d1.Print();
	//this指针实则为当前对象(d1)的地址,用date局部变量接收
	Date* date = &d1;
	date = nullptr;
	date->Print();
	date->TextFunc();
/
	date->SetDate(2022, 6, 1);
	return 0;
}

 出现编译错误!!!

 结论:成员函数由指针调用,则this指针(当前对象的地址)可能会为nullptr,但前提是不得对成员变量进行访问操作(成员变量有this指针形参访问),否则会出现编译错误

评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值