1.概要
- shared_ptr和weak_ptr的reset实验
- 用weak_ptr化解shared_ptr交叉引用的问题
2.代码
#include <iostream>
using namespace std;
template<typename T>
void fun(weak_ptr<T> wp) {
if (wp.expired()) {
cout << "Object has been released\n";
}
else {
cout << "Object not released\n";
}
}
namespace t1 {
void test() {
cout << "--- Release with shared_ptr -----------------------------\n";
shared_ptr<int> sh_ptr = make_shared<int>();
weak_ptr<int> wp(sh_ptr);
fun<int>(wp);//结果:Object not released
sh_ptr.reset();
fun<int>(wp);//结果:Object has been released
}
}
namespace t2 {
void test() {
cout << "--- Release with weak_ptr -----------------------------\n";
shared_ptr<int> sh_ptr = make_shared<int>();
weak_ptr<int> wp(sh_ptr);
fun<int>(wp);//结果:Object not released
//sh_ptr.reset();
wp.reset();
fun<int>(wp);//结果:Object has been released
}
}
namespace t3 {
class B;
class A
{
public:
A() {
cout << "A constructor call\n";
}
~A() {
cout << "A Destructor call\n";
}
shared_ptr<B> sh_ptr_b;
};
class B
{
public:
B() {
cout << "A constructor call\n";
}
~B() {
cout << "A Destructor call\n";
}
shared_ptr<A> sh_ptr_a;
};
void test() {
//这个实验会让交叉引用发生,导致对象无法析构
cout << "--- Cross references cannot be destructed -----------------------------\n";
shared_ptr<A> sh_ptr_a = make_shared<A>();
shared_ptr<B> sh_ptr_b = make_shared<B>();
cout << "ptr_a use_count: " << sh_ptr_a.use_count() << endl;
cout << "ptr_b use_count: " << sh_ptr_b.use_count() << endl;
sh_ptr_a.get()->sh_ptr_b = sh_ptr_b;
sh_ptr_b.get()->sh_ptr_a = sh_ptr_a;
//这里因为发生了交叉引用,所以对象最终不会析构,会发生内存泄露
cout << "ptr_a use_count: " << sh_ptr_a.use_count() << endl;
cout << "ptr_b use_count: " << sh_ptr_b.use_count() << endl;
}
/*
运行结果:最后没有调用析构函数
A constructor call
A constructor call
ptr_a use_count: 1
ptr_b use_count: 1
ptr_a use_count: 2
ptr_b use_count: 2
*/
}
namespace t4 {
class B;
class A
{
public:
A() {
cout << "A constructor call\n";
}
~A() {
cout << "A Destructor call\n";
}
//shared_ptr<B> sh_ptr_b;
//这是把shared_ptr<B>换成了weak_ptr<B>就化解了交叉引用
weak_ptr<B> sh_ptr_b;
};
class B
{
public:
B() {
cout << "A constructor call\n";
}
~B() {
cout << "A Destructor call\n";
}
shared_ptr<A> sh_ptr_a;
};
void test() {
//交叉引用的问题会得到解决
cout << "--- Cross reference problem solved -----------------------------\n";
shared_ptr<A> sh_ptr_a = make_shared<A>();
shared_ptr<B> sh_ptr_b = make_shared<B>();
cout << "ptr_a use_count: " << sh_ptr_a.use_count() << endl;
cout << "ptr_b use_count: " << sh_ptr_b.use_count() << endl;
sh_ptr_a.get()->sh_ptr_b = sh_ptr_b;
sh_ptr_b.get()->sh_ptr_a = sh_ptr_a;
//这里weak_ptr<B>会对这种引用做相应的处理所以 最终对象可以析构 不会发生内存泄露
cout << "ptr_a use_count: " << sh_ptr_a.use_count() << endl;
cout << "ptr_b use_count: " << sh_ptr_b.use_count() << endl;
}
/*
测试结果:调用了析构函数
A constructor call
A constructor call
ptr_a use_count: 1
ptr_b use_count: 1
ptr_a use_count: 2
ptr_b use_count: 1
A Destructor call
A Destructor call*/
}
int main()
{
t1::test();
t2::test();
t3::test();
t4::test();
cout << "Hello World!\n";
}
3.运行结果
--- Release with shared_ptr -----------------------------
Object not released
Object has been released
--- Release with weak_ptr -----------------------------
Object not released
Object has been released
--- Cross references cannot be destructed -----------------------------
A constructor call
A constructor call
ptr_a use_count: 1
ptr_b use_count: 1
ptr_a use_count: 2
ptr_b use_count: 2
--- Cross reference problem solved -----------------------------
A constructor call
A constructor call
ptr_a use_count: 1
ptr_b use_count: 1
ptr_a use_count: 2
ptr_b use_count: 1
A Destructor call
A Destructor call