原文网址:
WTF是WebKit中重要的C++类库,其中提供了大量实用的模板类,在WebKit的代码中得到广泛运用。在工作之中由于经常用到,在此总结一下,也算留个笔记。
顾名思义,OwnPtr表示“拥有”的意思。“拥有”这一词很玄妙,可能在这儿你还不知道它的深刻含义,没关系,看到RefPtr的时候你就知道了。
WTF::OwnPtr ptr = adoptPtr(new MyClass);
于是名为ptr的OwnPtr就构造好了。当ptr的析构函数被调用时,会立即调用MyClass类的析构函数,释放MyClass实例内存。这有什么用呢?我们来看一段代码。
-
MyClass * createInstance() {
-
MyClass *ret = new MyClass;
-
if (!checkA()) {
-
delete ret;
-
return NULL;
-
}
-
-
if (!checkB()) {
-
delete ret;
-
return NULL;
-
}
-
-
return ret;
-
}
上面的代码企图创建在进行checkA和checkB的检查后返回一个新的MyClass实例。看起来并没有什么问题,但如果中间的检查逻辑复杂繁多,那么有可能你会忘了进行 delete ret; 或者重复进行该操作,造成内存泄漏或者Crash。如果用OwnPtr来实现这个,有代码:
-
PassOwnPtr createInstance() {
-
OwnPtr ret = adoptPtr(new MyClass);
-
if (!checkA()) {
-
return NULL;
-
}
-
-
if (!checkB()) {
-
return NULL;
-
}
-
-
return ret.release();
-
}
这里为什么不需要用delete ret了呢?正是因为OwnPtr帮助你管理了这个指针。我们知道,当这个函数返回的时候,ret的析构函数(记住是OwnPtr的析构)会被调用,这时就会删除新创建的MyClass实例。而最后的ret.release()返回的是PassOwnPtr类型。这代表什么意思呢?这里就要从这个函数的意义来讲了。该函数创建一个新的MyClass实例,要有其它人负责最后释放这个实例。这个叫做“所有权转移”,createInstance函数刚开始构建新实例,所有权还在createInstance函数手里,当它返回的时候,所有权就交出去了。
这一“所有权转移”的过程表现在这个函数里就是,ret为createInstance函数所“拥有的”,当它完成构建后,调用 release 方法释放这个所有权,通过PassOwnPtr转交给其它人。所以这里可以知道,PassOwnPtr是负责“转移所有权的”,要确定所有权,你可以这样调用:
OwnPtr result = createInstance();
adoptPtr
而我们看到的adoptPtr又是干什么的呢?看看函数声明:
template PassOwnPtr adoptPtr(T*);
它接受一个裸指针,构造一个用于所有权转移的PassOwnPtr,然后丢给使用者OwnPtr。记住OwnPtr只接受PassOwnPtr类型的传递。
leakPtr
-
MyClass* createInstance() {
-
OwnPtr ret = adoptPtr(new MyClass);
-
if (!checkA()) {
-
return NULL;
-
}
-
-
if (!checkB()) {
-
return NULL;
-
}
-
-
return ret.leakPtr();
-
}
继续看以上的函数的另一种实现。如果我们坚持要返回裸指针,怎么办呢?使用leakPtr()来获取。leakPtr顾名思义就是“泄漏”裸指针出来使用。这个函数的作用是取消OwnPtr的管辖,即OwnPtr中的保存的裸指针被置为空,OwnPtr析构的时候不会删除任何东西。这也是所有权转移的一种手段,只是转移到的是一个裸指针,而不再是PassOwnPtr而已。
OwnPtr的常用使用方法
-
// 接收一个裸指针并创建为使用OwnPtr管理
-
OwnPtr a = adoptPtr(new MyClass);
-
-
// 读取裸指针的值(但不改变任何东西)
-
MyClass *ptr = a.get();
-
-
// 引用这个指针(和裸指针一样)
-
(*a).methodA();
-
-
// 直接访问这个指针(和裸指针一样)
-
a->methodA();
No related posts.
阅读(465) | 评论(0) | 转发(0) |