1.this指针(自引用指针)的概念引入
当定义了类的若干对象之后,系统会为每一个对象分配存储空间。如果一个类包含了成员函数和数据成员,就要分别为数据和函数的代码分配存储空间。
事实上,给对象赋值就是给对象的成员数据赋值,不同对象的存储单元中存放的数据值通常是不相同的,而不同对象的函数代码是相同的,无论调用哪一个对象的成员函数,其实调用的都是相同的代码。
C++的编译系统只用了一段空间来存放这个共同的函数代码段,在调用各个对象的成员函数时,都会去调用这个公用的函数代码段(这也是为什么类的大小不包括成员函数的原因)。
因此,每个对象的存储空间都只是该对象的数据成员所占的存储空间,而不包括成员函数代码所占的空间,函数代码是存储在对象之外的。
既然如此,每个对象都有自己的数据成员,但是对象的成员函数代码却合用一份。那么成员函数是怎样辨别出当前调用自己的是哪个对象,从而对该对象的数据成员而不是其他对象的数据成员进行处理呢?
就好比当我们进入一个房子之后,可以看见里面的桌子,椅子,地板等,但却看不到房子的全貌。对于一个实例而言,你可以看到该实例的数据成员和成员函数,但是实例本身我们是看不到的,而this指针时时刻刻指向这个实例。this指针的值是当前调用成员函数的对象的起始地址。
2.this指针的特性
<1>this指针的类型:类类型 *const
验证代码:
#include<iostream>
using namespace std;
class A
{
public:
void test(int y);
private:
int x;
};
void A::test(int y)
{
this = y;
cout<<y<<endl;
}
void Funtest()
{
A a;
a.test(4);
}
int main()
{
Funtest();
system("pause");
return 0;
}
运行结果:
<2>this指针本身并不是对象的一部分,所以不会影响sizeof的结果。
#include<iostream>
using namespace std;
class A
{
public:
void test();
private:
int x;
int y;
int z;
};
void A::test()
{
int n = sizeof(A);
cout<<n<<endl;
}
void Funtest()
{
A a;
a.test();
}
int main()
{
Funtest();
system("pause");
return 0;
}
运行结果:
<3>this指针的作用域在非静态数的内部。
#include<iostream>
using namespace std;
class A
{
public:
void test();
private:
int x;
};
void A::test()
{
cout<<this<<endl;
}
void Funtest()
{
A a;
a.test();
}
int main()
{
Funtest();
system("pause");
return 0;
}
<4>this指针是类成员函数的第一个默认隐含参数。
验证代码:
#include<iostream>
using namespace std;
class A
{
public:
void test(int y);
private:
int x;
};
void A::test(int y)
{
this->x = y;
cout<<y<<endl;
}
void Funtest()
{
A a;
a.test(4);
}
int main()
{
Funtest();
system("pause");
return 0;
}
运行结果:
<5>当数据成员名与成员函数的参数名相同时,必须显示调用this指针。
#include<iostream>
using namespace std;
class A
{
public:
void test(int x);
private:
int x;
};
void A::test(int x)
{
x = x;//错误,形参自己给自己赋值
this->x = x;//正确,将形参x的值赋值给当前对象的成员数据x
cout<<x<<endl;
}
void Funtest()
{
A a;
a.test(4);
}
int main()
{
Funtest();
system("pause");
return 0;
}
<6>this指针是系统自定义的,用户不必再重复定义。
<7>只有在非静态成员函数内部才能使用this指针,因为静态成员函数没有this指针。
#include<iostream>
using namespace std;
class A
{
public:
void test();
static void test1();
private:
int x;
};
void A::test()
{
cout<<this<<endl;
}
void test1()
{
cout<<this<<endl;
}
void Funtest()
{
A a;
a.test();
}
int main()
{
Funtest();
system("pause");
return 0;
}
错误提示:
<8>this指针是可以为空的。
#include<iostream>
using namespace std;
class A
{
public:
void test();
private:
int x;
};
void A::test()
{
cout<<this<<endl;
}
void Funtest()
{
A *a = NULL;
a->test();
}
int main()
{
Funtest();
system("pause");
return 0;
}
打印结果:
3.非静态成员函数的调用约定:_thiscall
<1>_thiscall只能用在类的非静态成员函数上。
<2>参数从右向左压栈。
<3>如果参数个数确定,this指针通过ecx传递给被调用者,如果参数不确定,this指针在所有参数压栈之后被压入堆栈。
<4>对于参数个数不确定的,调用者清理堆栈,否则函数自己清理堆栈。
4.为什么叫this指针而不是引用?
答:因为this指针存放当前正在调用对象的地址,而引用则是某个对象的别名,和该对象占同一块空间地址,二者区别还是蛮大的。