问题1:
Please choose the right statement of "this" pointer:( )
A. "this" pointer cannot be used in static functions.
B. "this" pointer could not be store in Register.
C. "this" pointer is constructed before member function.
D. "this" pointer is not counted for calculating the size of the object.
E. "this" pointer is read only.
======================================================================================
问题1解析:
关于this指针,有这样一段描述:当你进入了一个房子之后,你可以看风桌子、椅子、地板等,但是房子你是看不到全貌了。
对于一个类的实例来说,你可以看到它的成员函数、成员变量,但是实例本身呢?this指针是这样一个指针,它时时刻刻指向这个实例本向。
this指针易混的几个问题如下:
(1) this指针本质是一个函数参数,只是编译器隐藏起形式的,语法层面上的参数。
this只能在成员函数中使用,全局函数、静态函数都不能使用this。
实际上,成员函数默认第一个参数为 T* const this。
如:
class A
{
public :
int func(int p) {}
};
其中,func的原型在编译器看来应该是:
int func(A * const this, int p);
(2) this在成员函数的开始前构造,在成员的结束后清除。这个生命周期同任何一个函数的参数是一样的,没有任何区别。当调用一个类的成员函数时,编译器将类的指针作为函数的this参数传递进去。如:
A a;
a.func(10);
此处,编译器将会编译为:
A a;
a.func(&a, 10);
看起来和静态函数没差别,不过,区别还是有的。编译器通常会对this指针做一些优化,因此,this指针的传递效率比较高,如VC通常是通过ecx寄存器传递this参数的。
(3) this指针并不占用对象的空间。
this相当于非静态成员函数的一个隐形参数,不占对象的空间。它跟对象之间没有包含关系,只是当前调用函数的对象被它指向而已。
所有成员函数的参数,不管是不是隐含的,都不会占用对象的空间,只会占用参数传递时的栈空间,或者直接占用一个寄存器。
(4) this指针是什么时候创建的?
this在成员函数的开始执行前构造,在成员的执行结束后清除。
但是如果class或者struct里没有方法的活,它们是没有构造函数的,只能当做C的struct使用。采用TYPE XX的方式定义的话,在栈里分配内存,这时候this指针的值就是这块内存的地址。采用new方式创建对象的话,在堆里分配内存,new操作符通过eax返回分配的地址,然后设置给指针变量。之后去调用构造函数(如果有构造函数的话),这时将这个内存块的地址传给ecx。
(5) this指针存放在何处?堆、栈、还是其他?
this指针会因编译器不同而有不同的放置位置。可能是堆、栈,也可能是寄存器。
C++是一种静态的语言,那么对C++的分析应该从语法层面和实现层面两个方面进行。
语法上,this是指向对象的“常指针”,因此无法改变。它是一个指向相应对象的指针。所有对象共用的成员函数利用这个指针区别不同变量,也就是说,this是“不同对象共享相同成员函数”的保证。
而在实际应用的时候,this应该是个寄存器参数。这个不是语言规定的,而是“调用约定”,C++的默认调用约定是 _cdecl,也就是C风格的约定。该约定规定参数自右向左入栈,由调用方负责平衡堆栈。对于成员函数,将对象的指针(即this指针)存入ecx中(有的书将这一点单独分开,叫做thiscall,但是这的确也是cdecl的一部分)。因为这只是一个调用约定,不是语言的组成部分,不同编译器自然可以自由发挥。但是现在的主流编译器都是这么做的。
(6) this指针是如何传递给类中的函数的?绑定?还是在函数参数的首参数就是this指针?那么this指针又是如何找到“类实例后函数”的?
大多数编译器通过ecx寄存器传递this指针。事实上,这也是一个潜规则。一般来说,不同编译器都会遵从一致的传参规则,否则不同编译器产生的obj就无法匹配了。
(7) 我们只有获得一个对象后,才能通过对象使用this指针。如果我们知道一个对象this指针的位置,可以直接使用吗?
this指针只有在成员函数中才有定义。因此,你获得一个对象后,也不能通过对象使用this指针。所以,我们无法知道一个对象的this指针的位置(只有在成员函数里才有this指针的位置)。当然,在成员函数里,你是可以知道this指针的位置的(可以通过&this获得),也可以直接使用它。
答案:E