说三道四技术文摘-感悟人生的经典句子
说三道四 > 文档快照

请大家帮助我理解this指针的含义和用法(我仅剩的50分全部给了这个帖子)

编辑:说三道四文库 发布时间:2018-07-20 11:07
HTML文档下载 WORD文档下载 PDF文档下载
//以下代码不讨论static成员的情况,因为太多了我脑子就乱了
class Test{
public:  
  Test(int=0);
  void print()const;
private:
  int x;  
}

Test::Test(int a){x=a}
//问题1:x=a这个时候可以写成this->x=a吗?

void Test::print()const{
   cout<<"this->x ="<<this->x"<<endl;
}

int main(){
   Test tobj(12);
   tobj.print();
   
   //问题2:tobj.print()是不是可以理解为tobj.print(&tobj)?
   //问题3:如果问题2可以那样理解的话,那么this指针是不是就是成员函数的形参而已
   //只不过这个事情交给编译器来做了,所以我们调用成员函数的时候就可以省略掉了
   //函数定义部分是不是可以写成了void Test::print(Test *this)const{...}?
   //问题4:是不是有N个这样的成员函数就会有N个this指针?
   
   return 0;
}
请各位看看我这样理解对吗?还有什么错误的地方?谢谢!!!
问题1:可以。两者没有区别。实际上,编译器在编译时,会自动将x=a变成this->x=a再进行编译。

问题2:基本上可以这样理解。

问题3:this指针是成员函数的隐含形参。你不必写成void Test::print(Test *this),因为不管你写不写,编译器都会自动加上this指针作参数,你这样写,相当于void Test::print(Test *this, Test *this)

问题4:是的。

一般来说,仅在必要时需要显示使用this指针调用,例如:当参数与成员变量名相同时。
this指针是在类中成员函数默认的一个参数~
其指向引用的对象~
谢谢楼上的两位,补充一下:我的问题1是问在构造函数里就已经可以使用this指针了吗?偶有点疑惑,因为这个时候对象正在创建啊?(对不起,我这个人比较较真,所以麻烦了一点,大家不要生气)
问题1:可以。两者没有区别。实际上,编译器在编译时,会自动将x=a变成this->x=a再进行编译。

问题2:基本上可以这样理解。

问题3:这个是编译器给加的,你不必加,你知道就好了:(
问题4:是不是有N个这样的成员函数就会有N个this指针?

它是函数的形参,不是类的成员变量.你应该懂吧
我想是的,因为编译器为每个非静态函数都加了个tihis指针,所以我想构造函数也不例外吧
1、可以
this作用域是在类内部,该指针指向对象自己,因此,只要是成员函数都可以使用this,所以在成员函数test中可以使用this->x=a;
除了成员变量外,任何一个成员函数都可以通过this调用任何成员函数,包括函数本身;
假如类中有两个成员函数A(),B(),以下有效
test::A()
{
   ....
    this->B();
   ....
   this->A();//这里调用自己,使用了递归,不过需要判断处理,防止死循环
   ....
}

2,不对,
根据你的例子,成员函数print()打印输出的是成员变量X,&tobj是对象地址,也就是对象内部的this
应该理解为tobj.print(x),或者tobj.print(this->x)。



3,错误

4,每个类对象只有一个this(否则就不叫this了),你可以从对象角度理解,这个this就是指“本人”“myself”.
而this->x可以理解为“我的一部分”“我的手”

你再看看其他人怎么说的
楼主自己理解得差不多了
最好你再用C语言实现一遍,就更加清楚为什么一定要传this指针了。
问题3:普通成员函数的形参,是通过堆栈传递的,而this这个参数是通过ecx寄存器传的,假如对象在栈中定义,那么在栈中定义完对象后,程序通过ecx来访问对象本身,对象存储空间分配完后,自动调用构造函数。
越说越复杂,我越来越晕了...能不能说的通俗易懂点?
构造函数里就已经可以使用this指针了吗?

可以,这时对象已经有了,空间已经开辟了,所以this指针是有效的。

另外,问题3我坚持我的答案。this是成员函数隐含参数,C++教科书上有写。
同意楼上。

简单地说:每个对象有自己的独立的成员变量,
如果没 this 的话,成员函数会不知道应该使用哪一个对象的数据了。
晕...楼上的大哥强啊...我无语了:(
昨天晕了,还是不清楚,早上起来再T下
先写一个用于测试的小程序,
class test
{
private:
int prv_i;
int prv_j;
public:
int get_prv_i();
void set_prv_i(int i);

test(int i);
~test(){}
};

int test::get_prv_i()
{
return prv_i;
}

void test::set_prv_i(int i)
{
prv_i = i;
}

test::test(int i)
{
prv_j = i;
}

int main()
{
test tt(1),tt2(2);
tt.set_prv_i(20);
int i = tt.get_prv_i();

tt2.set_prv_i(30);
i = tt2.get_prv_i();

return 0;
}

然后编译之,用 g++ 加参数 -S 实现。

pushl $1
leal -24(%ebp), %eax  //传闻中的 this 指针?
pushl %eax
call __ZN4testC1Ei
下面的代码中有数行与上面4行类似,不知其是否与 this 指针有关。
//---------------------------------------------------------------
.file "a.cpp"
.text
.align 2
.globl __ZN4test9get_prv_iEv
.def __ZN4test9get_prv_iEv; .scl 2; .type 32; .endef
__ZN4test9get_prv_iEv:
pushl %ebp
movl %esp, %ebp
movl 8(%ebp), %eax
movl (%eax), %eax
popl %ebp
ret
.align 2
.globl __ZN4test9set_prv_iEi
.def __ZN4test9set_prv_iEi; .scl 2; .type 32; .endef
__ZN4test9set_prv_iEi:
pushl %ebp
movl %esp, %ebp
movl 8(%ebp), %edx
movl 12(%ebp), %eax
movl %eax, (%edx)
popl %ebp
ret
.align 2
.globl __ZN4testC2Ei
.def __ZN4testC2Ei; .scl 2; .type 32; .endef
__ZN4testC2Ei:
pushl %ebp
movl %esp, %ebp
movl 8(%ebp), %edx
movl 12(%ebp), %eax
movl %eax, 4(%edx)
popl %ebp
ret
.align 2
.globl __ZN4testC1Ei
.def __ZN4testC1Ei; .scl 2; .type 32; .endef
__ZN4testC1Ei:
pushl %ebp
movl %esp, %ebp
movl 8(%ebp), %edx
movl 12(%ebp), %eax
movl %eax, 4(%edx)
popl %ebp
ret
.def ___main; .scl 2; .type 32; .endef
.align 2
.globl _main
.def _main; .scl 2; .type 32; .endef
_main:
pushl %ebp
movl %esp, %ebp
subl $72, %esp
andl $-16, %esp
movl $0, %eax
addl $15, %eax
addl $15, %eax
shrl $4, %eax
sall $4, %eax
movl %eax, -60(%ebp)
movl -60(%ebp), %eax
call __alloca
call ___main
pushl $1
leal -24(%ebp), %eax
pushl %eax
call __ZN4testC1Ei
addl $8, %esp
pushl $2
leal -40(%ebp), %eax
pushl %eax
call __ZN4testC1Ei
addl $8, %esp
pushl $20
leal -24(%ebp), %eax
pushl %eax
call __ZN4test9set_prv_iEi
addl $8, %esp
leal -24(%ebp), %eax
pushl %eax
call __ZN4test9get_prv_iEv
addl $4, %esp
movl %eax, -44(%ebp)
pushl $30
leal -40(%ebp), %eax
pushl %eax
call __ZN4test9set_prv_iEi
addl $8, %esp
leal -40(%ebp), %eax
pushl %eax
call __ZN4test9get_prv_iEv
addl $4, %esp
movl %eax, -44(%ebp)
subl $12, %esp
leal -40(%ebp), %eax
pushl %eax
call __ZN4testD1Ev
addl $16, %esp
subl $12, %esp
leal -24(%ebp), %eax
pushl %eax
call __ZN4testD1Ev
addl $16, %esp
movl $0, %eax
L6:
L8:
L5:
leave
ret
.section .text$_ZN4testD1Ev,"x"
.linkonce discard
.align 2
.globl __ZN4testD1Ev
.def __ZN4testD1Ev; .scl 2; .type 32; .endef
__ZN4testD1Ev:
pushl %ebp
movl %esp, %ebp
popl %ebp
ret
-_-!!不动汇编的说.......郁闷.....楼上的大哥有什么结论就说吧?
实际上我们不提倡在构造函数中显式地使用this指针,有些编译器可能会给出警告。
实际情况是:当控制进入构造函数时,当前对象的内存空间已经分配妥当,但是仍然处于未初始化的状态,也就是说,此时语句this->x实际上是在访问一个未经初始化的内存空间。例如:

class Derived;
class Base{
public:
    explicit
    Base(Derived *p) : pd_(p){}
    ...

private:
    Derived *pd_;
};

class Derived : public Base{
public:
    Derived() : Base(this) {}
    ...
};

解决的办法是:使用成员初始化列表,而不要在构造函数体内初始化数据成员,因为那是赋值而不是初始化。

编译会扩展出this的
偶T
刚听到一个解释
“其实this指针只是一个名称而已,对象中并这个变量的存在,只是成员函数的参数里面编译器多加了一个指向对象自身的指针,我们给他起了个名称叫this指针啦” 

我自己理解了下,这样的解释让我感觉this指针有点像变量引用参数
int a=1
int &r=a
r++
//r++就是a++
不为r分配存储单元但他就是存在,而且代表a
1.可以
2.不可以
An object's this pointer is not part of the object itself; it is not reflected in the result of a sizeof statement on the object. Instead, when a nonstatic member function is called for an object, the address of the object is passed by the compiler as a hidden argument to the function. For example, the following function call:
myDate.setMonth( 3 );
can be interpreted this way:
setMonth( &myDate,3);
备案号:鲁ICP备13029499号-2 说三道四 www.s3d4.cn 说三道四技术文摘