引用计数,oc进行内存管理的一个技术。此计数记录了一个对象被指针指向的次数。提到指针,很多书籍都将指针比喻成牵牛的绳子。那oc种的牵牛绳牵的是一头很聪明的牛,当它察觉到自己身上不再有绳子牵着的时候就会跑掉,更神奇的是自个儿跑回牛棚里(对应的概念就是当引用计数为0的时候,内存被释放,释放的内存可被系统再分配)。
现在我们自己实现这一简单的功能,选择用c++的原因是,c++有操作符重载,以及析构函数。这对于我们要实现的简陋内存管理是非常方便的.
首先根类NSObject的代码如下:
class NSObject
{
public:
int refereceCount_;
public:
NSObject()
{
refereceCount_ = 0;
}
NSObject(int _ix)
{
refereceCount_ = 0;
}
NSObject(string name)
{
refereceCount_ = 0;
name_ = name;
}
~NSObject()
{
cout <
两个成员变量 refereceCount_ 和 name_,分别是引用计数和对象标识。引用计数存放在对象里的原因显而易见,因为这样只需保持一份,一处更改处处生效。如果存放在指针中,就存在更新引用计数要一同更新多个副本的问题。
指针类:
class Pointer
{
public:
virtual Pointer& operator = (NSObject * pt) = 0;
virtual ~Pointer()
{
}
};
指针类要实现两个功能,一是指向对象,二是指针相互赋值。这里就是重载了赋值操作符实现的。主要看看这个StrongPointer:
class StrongPointer:public Pointer
{
public:
Pointer& operator = (NSObject * pt)
{
pt2Object_ = pt;
if(pt != NULL)
pt->refereceCount_ ++;
cout << "强绳子套住 ("<name_<<") ,引用计数加1,此时的引用计数为 "<refereceCount_<refereceCount_ --;
cout << "绳子将要被解除 ,(" <name_<<") 引用计数减1,此时的引用计数为 "<refereceCount_<refereceCount_ == 0)
delete pt2Object_;
}
pt2Object_ = pointer.pt2Object_;
if(pt2Object_ != NULL)
pt2Object_->refereceCount_ ++;
cout << "强绳子套住 (" << pointer.pt2Object_->name_<<"),引用计数加1,此时的引用计数为 "<refereceCount_<refereceCount_ --;
cout << "绳子将要被解除 ,(" <name_<<") 引用计数减1,此时的引用计数为 "<refereceCount_<refereceCount_ == 0)
delete pt2Object_;
}
pt2Object_ = pointer.pt2Object_;
if(pt2Object_ != NULL)
pt2Object_->refereceCount_ ++;
cout << "强绳子套住 (" << pointer.pt2Object_->name_<<"),引用计数加1,此时的引用计数为 "<refereceCount_<refereceCount_ --;
if(pt2Object_->refereceCount_ == 0)
{
cout << "强绳子被解除, ("<name_<<") 引用计数减1,此时引用计数为0"<name_<<") 引用计数减1,此时的引用计数为 "<refereceCount_ <
主要看以下两个函数
Pointer& operator = (NSObject * pt) 和 StrongPointer& operator = (const StrongPointer &pt) 分别接受对象(虽然这里实际上还是对象的指针,这个指针是c++概念里的指针,StrongPointer类的对象才是我们要表示这个牵牛绳的物件。)
和另一个指针类实体。 所做的事情也很简单 ,将所指向的对象的引用计数加一。_refereceCount设为公有是很不负责任的行为,但是为了方便,暂且就这么做了。
另外一个重要的点就是这个析构函数,当指针类自身被销毁的时候,也就是牵牛绳不在了的时候,牛是要记住自己身上的牵牛绳少了一根的,特别的,当牵牛绳统统都不见了,牛就跑回牛棚(内存被系统回收.)
测试看下结果:
StrongPointer s_pt1 ;
s_pt1 = new NSObject("黄牛");
StrongPointer * s_pt2 = new StrongPointer();
*s_pt2 = new NSObject("黑牛");
可以看到的是 我们找来了两个 “绳子” ,s_pt1,spt_2。这两个"绳子"分别来自栈和堆,当程序运行结束时 栈上的“绳子”就会被自动解除,于是它栓的牛也就跑了
看另外一段代码:
StrongPointer s_pt1 ;
s_pt1 = new NSObject("黄牛");
StrongPointer * s_pt2 = new StrongPointer();
*s_pt2 = new NSObject("黑牛");
*s_pt2 = s_pt1;
同样还是两根绳子,原本是黄牛跑回了牛棚,这次我们将原本栓在黑牛身上的绳子拴在了黄牛身上,于是黑妞就当场跑了。黄牛身上有两个绳子,一个会自动销毁,一个不会,于是最后黄牛还是会被拴在原地。