智能指针循环引用:
当两个shared_ptr智能指针调用两个相互调用的类的时候依然会存在内存泄露的情况,因为只有到user_count=0的时候才能释放该智能指针相互都在等待对方释放资源:`
class Parent;
typedef std::shared_ptr<Parent> ParentPtr;
class Child{
public:
ParentPtr father;
~Child();
Child;
};
typedef std::shared_ptr<Child> ChildPtr;
class Parent{
public:
ChildPtr son;
~Parent();
Parent();
};
Child::Child(){std::count<<"hello child\n";}
Parent::Parent(){std::cout<<"hello parent\n";}
Child::~Child(){std::cout<<"bye child\n";}
Parent::~Parent(){std::cout<<"bye parent\n";}
void testParentAndChild(){
ParentPtr p(new Parent());
ChildPtr c(new Child());
p->son = c; //c.use_count () == 2 and p.use_count() == 1
c->father = p; //c.use_count() == 2 p.use_count() == 2
}
用weak_ptr可以打破智能指针循环引用所出现的问题。
当外部有share_ptr在管理weak_ptr资源时则该指针是有效的,否则无效用lock()来控制
void sharedPtrWithWeakPtr() {
ObjectPtr obj(new Object(1));
typedef std::weak_ptr<Object> WeakObjectPtr;
WeakObjectPtr weakObj2;
WeakObjectPtr weakObj(obj);
WeakObjectPtr weakObj3(obj);
std::cout << "obj use count is " << obj.use_count() << std::endl; // 1
{
auto p = weakObj.lock(); // auto === ObjectPtr
if(p) {
std::cout << p.unique() << std::endl; // false p.use_count() >= 2
// do what you want to do
} else {
}
}
obj.reset(new Object(2));
{
auto p = weakObj.lock();
if(p) {
assert(false);
// do what you want to do
} else {
}
}
weakObj = obj;
if(weakObj.expired()) {
} else {
}
}
如果调用reset()后再调用lock()永远只会false,如果reset一个new资源原有的也会false
再=obj时weak_ptr指针就会又有效,可以用weak_ptr的expired()函数来判断该指针是否有管理资源
obj.reset();
auto p = weakObj.lock();
if(p){
asset(false);
//do what you want to do
}else{
}
obj.reset(new Object(2));
auto p = weakObj.lock();
if(p){
asset(false);
//do what you want to do
}else{
}
weakObj = obj;
if(weakObj.expired()){
}else{
}
只要让shared_ptr循环引用中打破一环,shared_ptr就能发挥它应有的作用,下例程序可正常运行:
class Parent;
typedef std::weak_ptr<Parent> ParentPtr;
class Child{
public:
ParentPtr father;
~Child();
Child;
};
typedef std::shared_ptr<Child> ChildPtr;
class Parent{
public:
ChildPtr son;
~Parent();
Parent();
};