现在的位置: 首页 > 综合 > 正文

C++ this指针解析

2013年08月14日 ⁄ 综合 ⁄ 共 2339字 ⁄ 字号 评论关闭

this指针我并不陌生,学过java的都知道,this在java中也经常出现。今天我专门研究了一下C++中的this指针。

http://www.cnblogs.com/hnrainll/archive/2011/05/20/2051939.html

this指针指向的就是调用该方法的对象,对this的解引用*this就是调用该方法的对象。

this指针的含义及其用法: 
1. this指针是一个隐含于每一个成员函数中的特殊指针。它指向正在被该成员函数操作的那个对象。
2. 当对一个对象调用成员函数时,编译程序先将对象的地址赋给this指针,然后调用成员函数,每次成员函数存取数据成员时,由隐含使用this指针。(参加下面的例子)
3. 当一个成员函数被调用时,自动向它传递一个隐含的参数,该参数是一个指向这个成员函数所在的对象的指针。
4. 在C++中,this指针被隐含地声明为: X *const this,这意味着不能给this 指针赋值;
   在X类的const成员函数中,this指针的类型为:const X* const, 这说明this指针所指向的这种对象是不可修改的(即不能对这种对象的数据成员进行赋值操作);

5. 由于this并不是一个常规变量,所以,不能取得this的地址。
6. 在以下场景中,经常需要显式引用this指针
   (1)为实现对象的链式引用
   (2)为避免对同一对象进行赋值操作
   (3)在实现一些数据结构时,如list.

一个对象的this指针并不是对象本身的一部分,不会影响 sizeof(对象)的结果。this作用域是在类内部,当在类的非静态成员函数中访问类的非静态成员的时候,编译器会自动将对象本身的地址作为一个隐含参数传递给函数。也就是说,即使你没有写上this指针,编译器在编译的时候也是加上this的,它作为非静态成员函数的隐含形参,对各成员的访问均通过 this进行。

你认为它可以顺利执行吗?

class A {

    public:

        void Hello(conststd::string& name) {

           std::cout <<"hello " << name;

         }

};

int main(int argc, char** argv)

{

    A* pa = NULL; //!!

   pa->Hello("world");

    return 0;

}

试试的确可以顺利运行输出helloworld,奇怪吗?其实并不奇怪,根据C++对象模型,类的非虚方法并不会存在于对象内存布局中,实际上编译器是把Hello方法转化成了类似这样的全局函数

void A_Hello_xxx(A * const this, const std::string& name) {

    std::cout << “hello“ << name;

}


对象指针其实是作为第一个参数被隐式传递的,pa->Hello(“world”)实际上是调用的A_Hello_xxx(pa,“world”),而恰好A_Hello_xxx内部没有使用pa,所以这段代码得以顺利运行。

对于类成员函数而言,并不是一个对象对应一个单独的成员函数体,而是此类的所有对象共用这个成员函数体。当程序被编译之后,此成员函数地址即已确定。而成员函数之所以能把属于此类的各个对象的数据区别开, 就是靠这个this指针。函数体内所有对类数据成员的访问,都会被转化为this->数据成员的方式。

http://blog.csdn.net/starlee/article/details/2062586

给出了如下的例子:

class CNullPointCall

{

public:

   static void Test1();

   void Test2();

   void Test3(int iTest);

   void Test4();

 

private:

   static int m_iStatic;

   int m_iTest;

};

 

int CNullPointCall::m_iStatic = 0;

 

void CNullPointCall::Test1()

{

   cout << m_iStatic << endl;

}

 

void CNullPointCall::Test2()

{

   cout << "Very Cool!" << endl;

}

 

void CNullPointCall::Test3(int iTest)

{

   cout << iTest << endl;

}

 

void CNullPointCall::Test4()

{

   cout << m_iTest << endl;

}

 

CNullPointCall *pNull = NULL; // 没错,就是给指针赋值为空

pNull->Test1(); // call 1

pNull->Test2(); // call 2

pNull->Test3(13); // call 3

pNull->Test4(); // call 4

除了call 4那行代码以外,其余3个类成员函数的调用都是成功的,都能正确的输出结果,而且包含这3行代码的程序能非常好的运行。
    经过细心的比较就可以发现,call 4那行代码跟其他3行代码的本质区别:类CNullPointCall的成员函数中用到了this指针。对于上面的例子来说,this的值也就是pNull的值。也就是说this的值为NULL。而Test1()是静态函数,编译器不会给它传递this指针,所以call 1那行代码可以正确调用(这里相当于CNullPointCall::Test1());对于Test2()和Test3()两个成员函数,虽然编译器会 给这两个函数传递this指针,但是它们并没有通过this指针来访问类的成员变量,因此call
2和call 3两行代码可以正确调用;而对于成员函数Test4()要访问类的成员变量,因此要使用this指针,这个时候发现this指针的值为NULL,就会造成程序的崩溃。
 ”

抱歉!评论已关闭.