- 1.安卓轻量级智能指针
- 2.指针互相引用带来死锁问题
- 3.安卓弱指针的引进
- 4.修改代码,引入弱指针
在c++智能指针的简单实现与改进中实现了简单的智能指针,但是还是存在缺陷,当多线程操作RefBase中引用的值时得到的可能不是我们想要的,这是由于对RefBase中的引用计数非原子性导致,在Android中实现了轻量级智能指针保证了对引用计数的原子性
安卓源码路径:
frameworks/rs/cpp/util/RefBase.h
实现:
templateclass LightRefBase { public: inline LightRefBase() : mCount(0) { } inline void incStrong(__attribute__((unused)) const void* id) const { __sync_fetch_and_add(&mCount, 1); } inline void decStrong(__attribute__((unused)) const void* id) const { if (__sync_fetch_and_sub(&mCount, 1) == 1) { delete static_cast (this); } } //! DEBUGGING ONLY: Get current strong ref count. inline int32_t getStrongCount() const { return mCount; } typedef LightRefBase basetype; protected: inline ~LightRefBase() { } private: friend class ReferenceMover; inline static void moveReferences(void*, void const*, size_t, const ReferenceConverterBase&) { } private: mutable volatile int32_t mCount; };
注意点:
__sync_fetch_and_add(&mCount, 1):对引用计数加1
if (__sync_fetch_and_sub(&mCount, 1) == 1) {
delete static_cast(this);
}
先用__sync_fetch_and_sub(&mCount, 1) == 1进行减1操作,使用该函数返回的是mCount被减去1之前的值,即此时mCount为0,返回值为1,会将目标对象进行删除操作,实际上还存在着问题,轻量级智能指针保证了对引用计数的原子性,但无法保证对目标对象的销毁,当执行__sync_fetch_and_sub(&mCount, 1) == 1刚好线程被切换出去,刚好此线程对对象进行赋值操作,后面切换回来将对象删除。所以需要程序员自己去考虑如何使用
2.指针互相引用带来死锁问题下面一个程序存在一个问题,对象之间互相引用导致程序结束对象依旧没有销毁
#include#include #include #include "RefBase.h" using namespace std; using namespace android::RSC; class Person : public LightRefBase { private: sp father; sp son; public: Person() { cout <<"Pserson()"< cout << "~Person()"< &father) { this->father = father; } void set_son(sp &son) { this->son = son; } void print_info(void) { cout<<"just for test"< sp father = new Person(); sp son = new Person(); father->set_son(son); son->set_father(father); } int main(int argc, char **argv) { test_func(); return 0; }
需要注意的点:
- 如果对象中含有其他对象成员时,先构造其他对象成员,再构造自身,所以在sp
father = new Person();和 sp son = new Person(),都先构造father和son,再构建person自身 - 再将person对象的指针传给sp
father或者sp son,从而调用 sp(T* other) ,增加了person对象的引用计数(此时值为1) - 调用set_father或者set_son操作会使自身的person对象引用计数+1,此时计数为2
- 当test_func函数结束时,father和son被析构,对于father来说,调用~sp()之后引用计数减1,此时引用计数为1,对son也是如此,所以father和son这两个对象都没有被销毁
存在问题:
- 对象father和son互相引用,决定对方的生死,这种引用方式叫做强引用,要想解决强引用带来的对象无法销毁,只有引入弱引用才可以解决,解决的办法是一个使用强指针,一个使用弱指针
- 强引用/强指针:A指向B,A决定B的生死
- 弱引用/弱指针:A指向B,A不能决定B的生死
csdn已经有很多优秀的博客讲解强弱指针,可以参考下面文章
Android 系统C++智能指针----总结
Android基础–智能指针
#include#include #include #include using namespace std; using namespace android; class Person : public RefBase { private: char *name; wp father; wp son; public: Person() { cout <<"Pserson()"< cout <<"Pserson(char *name)"< name = name; } ~Person() { cout << "~Person()"< &father) { this->father = father; } void set_son(sp &son) { this->son = son; } char *get_name(void) { return name; } void print_info(void) { sp f = father.promote(); sp s = son.promote(); cout<<"I am "< getName()< getName()< sp father = new Person("LiYiShi");//1 sp son = new Person("LiErShi");//2 father->set_son(son);//3 son->set_father(father);//4 } int main(int argc, char **argv) { test_func(); return 0; }
结果:
~Person() ~Person()
可以看到两个person对象都调用了析构函数
- 1,2过程会使两个Person对象的强引用计数+1,弱引用计数加1
- 3,4过程会使两个person对象的弱引用+1
- 所以函数结束之后会调用两个对象的析构函数,强引用计数减为0
注意:
- 但是对于弱指针wp,若想调用目标对象中的某些方法时,需要使用promote方法把它升级为强指针,升级完后要判断返回值,因为弱指针只是简单的引用某个对象而已,并不保证对象已经消亡



