介绍
weak_ptr是弱智能指针对象,它不控制所指向对象生存期的智能指针,它指向由一个shared_ptr管理的智能指针。将一个weak_ptr绑定到一个shared_ptr对象,不会改变shared_ptr的引用计数。一旦最后一个所指向对象的shared_ptr被销毁,所指向的对象就会被释放,即使此时有weak_ptr指向该对象,所指向的对象依然被释放。
代码验证如下:
//default consstructor
weak_ptr<string> wp;
{
shared_ptr<string> p = make_shared<string>("hello world!\n");
//weak_ptr对象也绑定到shared_ptr所指向的对象。
wp = p;
cout << "use_count: " <<wp.use_count() << endl;
}
//wp是弱类型的智能指针,不影响所指向对象的生命周期,
//这里p已经析构,其所指的对象也析构了,因此输出是0
cout << "use_count: " << wp.use_count() << endl;
运行结果:
use_count: 1
use_count: 0
weak_ptr智能指针使用如下:
void test_valid(weak_ptr<string> &wp)
{
if(shared_ptr<string> smptr2 = wp.lock())
{
cout << "the shared_ptr is valid\n";
}
else
{
cout << "the shared_ptr is not valid\n";
}
//检查被引用的对象是否已删除 false 仍存在 true 释放
if(!wp.expired())
{
//it is getting valid shared_ptr obj now;
shared_ptr<string> smptr1 = wp.lock();
cout << " get obj value: " << *smptr1;
}
}
int main()
{
shared_ptr<string> p = make_shared<string>("hello world!\n");
//default consstructor
weak_ptr<string> wp1;
//copy constructor
weak_ptr<string> wp2(p);
//assign constructor
weak_ptr<string> wp3 = wp2;
test_valid(wp2);
//释放被管理对象的所有权, 调用后 *this 不管理对象
wp2.reset();
test_valid(wp2);
return 0;
}
运行结果:
the shared_ptr is valid
get obj value: hello world!
the shared_ptr is not valid
循环引用
weak_ptr可以解决shared_ptr循环引用问题,导致内存泄漏问题,问题模型如下图:
当shared_ptr类型的spA、spB对象析构时,ref_count 减一;由于Obj A 和 Obj B中的shared_ptr智能指针还相互引用,导致ref_count不为零,spA和spB不会去析构所指的对象,最终导致内存泄漏。
当Obj A 和 Obj B中的智能指针是weak_ptr是,不会影响share_ptr智能指针引用计数,当spA和spB析构时,导致ref_count为零,同时所指向的对象也就被析构了;其解决方案模型如下:
代码实例如下:
//strong reference
class B;
class A
{
public:
shared_ptr<class B> m_spB;
};
class B
{
public:
shared_ptr<class A> m_spA;
};
//weak reference
class WeakB;
class WeakA
{
public:
weak_ptr<class WeakB> m_wpB;
};
class WeakB
{
public:
weak_ptr<class WeakA> m_wpA;
};
void test_loop_ref()
{
weak_ptr<class A> wp1;
{
auto pA = make_shared<class A>();
auto pB = make_shared<class B>();
pA->m_spB = pB;
pB->m_spA = pA;
wp1 = pA;
}//内存泄漏
cout << "wp1 reference number: " << wp1.use_count() << "\n";
weak_ptr<class WeakA> wp2;
{
auto pA = make_shared<class WeakA>();
auto pB = make_shared<class WeakB>();
pA->m_wpB = pB;
pB->m_wpA = pA;
wp2 = pA;
}//无内存泄漏
cout << "wp2 reference number: " << wp2.use_count() << "\n";
}
int main()
{
//std::weak_ptr 用来避免 std::shared_ptr 的循环引用
test_loop_ref();
return 0;
}
wp1和wp2作为shared_ptr智能指针的核查器,其检测结果如下:
wp1 reference number: 1//内存泄漏
wp2 reference number: 0//问题解决