指针和引用以及CString实现机制

指针和引用以及CString实现机制

涵之 发表于 2007-03-18 19:27:42
指针和引用  
  引用,一个变量的别名,为什么引入别名呢?原因是我们想定义一个变量,他共享另一个变量的
内存空间,使用别名无疑是一个好的选择。变量是什么?是一个内存空间的名字,如果我们给这个
内存空间在起另外一个名字,那就是能够共享这个内存了,引用(别名)的由此而来。
    指针,指向另一个内存空间的变量,我们可以通过它来索引另一个内存空间的内容,本身有自己的
内存空间。
    二者区别:(1)引用访问一个变量是直接访问,而指针是间接访问。
            (2)引用是一个变量的别名,本身不单独分配自己的内存空间,而指针有自己的内存空间。
            (3)引用在开始的时候就绑定到了一个内存空间(开始必须赋初值),所以他只能是这个
内存空间的名字,而不能改成其他的,当然可以改变这个内存空间的值.
    例如
    int i = 3,j = 4;
    int &x = i;//成为i的别名
    x = j;//不能否认x仍然引用i,并没有成为j的别名,只是修改了x和j共享的内存空间的值.
    这点与指针不同,指针在任何时刻都可以改变自己的指向.



指针的引用与正常指针
释放内存的另一例比较

一、代码:

 

#include <iostream>

using namespace std;

void freePtr1(int* p1)

{

   delete p1;

   p1 = NULL;

}

void freePtr2(int*& p2)

{

   delete p2;

   p2 = NULL;

}

 

void main()

{

   int *p1 = new int;

   *p1 = 1;

   freePtr1(p1);

   int *p2 = new int;

   *p2 = 2;

   freePtr2(p2);

   system("pause");

}

思考:在freePtr1freePtr2 的比较中,你能发现它们的不同点吗?

 

二、对代码进行解释:

#include <iostream>

using namespace std;

void freePtr1(int* p1)

{

   //未释放内存前 ->  p1 Address : 0012FDDC  p1 value : 003429B8,在这里,p1它也是一个变量,既然是一个变量,那么它将会以值的传递,把外部变量p1传到栈内,在栈内产生一个地址:0012FDDC,当然,它的值不会变仍然是指向堆地址:003429B8

   delete p1; //系统回收p1值的地址003429B8处的内存。

p1 = NULL;//p1赋以NULL值即:00000000,注意:p1本身的地址并没有变,变的是p1的值。

   //释放内存后 ->  p1 Address : 0012FDDC  p1 value : 00000000,出栈后,p1由于是一个临时对象,出栈后它会自动被视为无效。

}

void freePtr2(int*& p2)

{

   //未释放内存前 ->  p2 Address : 0012FEC8  p2 value : 003429B8p2是一个指针的引用,即引用指向指针,记住引用的特点:对引用的对象直接操作。所以它的地址和值与栈外的main()函数中,p2的值是同一个。

   delete p2; //p2所引用的指针进行释放内存,即:系统回收main()函数中 p2的值 003429B8 地址处的内存。

   p2 = NULL;//main()函数中p2的指针赋以NULL值。

   //释放内存后 ->  p2 Address : 0012FEC8  p2 value : 00000000,由于操作的对象都是main()函数中的p2,所以它将应用到原变量中。

}

 

void main()

{

   int *p1 = new int;

//释放内存前->  p1 Address : 0012FED4  p1 value : 003429B8

   freePtr1(p1);

   //释放内存后->  p1 Address : 0012FED4  p1 value : 003429B8

 

   int *p2 = new int;

   //释放内存前->  p2 Address : 0012FEC8  p2 value : 003429B8

   freePtr2(p2);

   //释放内存后->  p2 Address : 0012FEC8  p2 value : 00000000

   system("pause");

}




 CString实现的机制

   CString是通过“引用”来管理串的,“引用”这个词我相信大家并不陌生,象Window内核对象、COM对象等都是通过引用来实现的。而CString也是通过这样的机制来管理分配的内存块。实际上CString对象只有一个指针成员变量,所以任何CString实例的长度只有4字节.

       : int len = sizeof(CString);//len等于4

这个指针指向一个相关的引用内存块,如图: CString str("abcd");                                         

      0x04040404                           head部,为引用内存块相关信息

                                                                   

         str                               0x40404040
正因为如此,一个这样的内存块可被多个CString所引用,例如下列代码:

CString str("abcd");

CString a = str;

CString b(str);

CString c;

c = b;

上面代码的结果是:上面四个对象(str,a,b,c)中的成员变量指针有相同的值,都为0x40404040.而这块内存块怎么知道有多少个CString引用它呢?同样,它也会记录一些信息。如被引用数,串长度,分配内存长度。

这块引用内存块的结构定义如下:

struct CStringData

{

  long nRefs;       //表示有多少个CString 引用它. 4

  int nDataLength;  //串实际长度. 4

  int nAllocLength; //总共分配的内存长度(不计这头部的12字节). 4

};

由于有了这些信息,CString就能正确地分配、管理、释放引用内存块。

如果你想在调试程序的时候获得这些信息。可以在Watch窗口键入下列表达式:

(CStringData*)((CStringData*)(this->m_pchData)-1)

(CStringData*)((CStringData*)(str.m_pchData)-1)//str为指CString实例

 

正因为采用了这样的好机制,使得CString在大量拷贝时,不仅效率高,而且分配内存少。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值