探究一下osg中的智能指针:osg::ref_ptr。
一、首先注意,智能指针是个模板类(不要以为理解了这句话)。比如这样一个定义:
osg::ref_ptr<osg::Vec3Array> pArray = new osg::Vec3Array;
这里,pArray本质上是一个ref_ptr对象(并非是指针),而之所以可以将new返回的指针赋给他是因为osg::ref_ptr重写了赋值操作符(关于赋值操作符的重写原则见effective c++)。而之气以可以对pArray解引用作*操作,是因为osg::ref_ptr重写了*操作符。
二、对赋值操作符的重写有两个版本
1.版本1是将ref_ptr&赋给一个ref_ptr对象
ref_ptr& operator = (const ref_ptr& rp) { assign(rp); return *this; }
assign进行了维护引用计算的操作:
template<class Other> void assign(const ref_ptr<Other>& rp) { if (_ptr==rp._ptr) return; T* tmp_ptr = _ptr; _ptr = rp._ptr; if (_ptr) _ptr->ref(); // 对右操作数rp引用加1,同时左操作数引用减1 // unref second to prevent any deletion of any object which might // be referenced by the other object. i.e rp is child of the // original _ptr. if (tmp_ptr) tmp_ptr->unref(); }
赋值时,两个ref_ptr的模板可以不同(只限这个版本的重载)。
2.版本2是将指向模板的指针赋给ref_ptr
inline ref_ptr& operator = (T* ptr) { if (_ptr==ptr) return *this; T* tmp_ptr = _ptr; _ptr = ptr; if (_ptr) _ptr->ref(); // unref second to prevent any deletion of any object which might // be referenced by the other object. i.e rp is child of the // original _ptr. if (tmp_ptr) tmp_ptr->unref(); return *this; }
这个版本较长使用。
这里可以看到,如果想用智能指针,就必须要有引用计数,即模板类必须要有ref方法,在osg中就体现在必须要继承自osg::Reference。例如osg::Vec3,他就不可以作为ref_ptr的模板。
三、重写解引用操作符
T& operator*() const { return *_ptr; }
这里_ptr是指向模板T的指针,如此便返回了_ptr所指对象的引用。
四、重载箭头操作符
T* operator->() const { return _ptr; }
这里箭头操作符得到的是指向T的指针,故而,上列pArray->返回的是指向osg::Vec3Array的指针,然后可以调用Vec3Array的方法。
五、重载比较操作符
bool operator == (const ref_ptr& rp) const { return (_ptr==rp._ptr); } bool operator == (const T* ptr) const { return (_ptr==ptr); } friend bool operator == (const T* ptr, const ref_ptr& rp) { return (ptr==rp._ptr); } bool operator != (const ref_ptr& rp) const { return (_ptr!=rp._ptr); } bool operator != (const T* ptr) const { return (_ptr!=ptr); } friend bool operator != (const T* ptr, const ref_ptr& rp) { return (ptr!=rp._ptr); } bool operator < (const ref_ptr& rp) const { return (_ptr<rp._ptr); }