shared_ptr存在的问题
shared_ptr 内部维护了一个共享的引用计数器,多个shared_ptr可以指向同一个资源,如果出现循环引用的情况,引用计数将永远无法归0, 资源不会被释放。
#include <iostream>
#include <memory>
#include<string>
using namespace std;
class BB;
class AA {
public:
string m_name;
shared_ptr<BB> m_p;
AA() {
cout << m_name << "调用了AA的构造函数"<< endl;
}
AA(const string &name):m_name(name) {
cout << "调用了AA的构造函数("<<m_name<<")"<< endl;
}
~AA() {
cout << "调用了AA的析构函数("<<m_name<<")"<< endl;
}
};
class BB {
public:
string m_name;
shared_ptr<AA> m_p;
BB() {
cout << m_name << "调用了BB的构造函数"<< endl;
}
BB(const string &name):m_name(name) {
cout << "调用了BB的构造函数("<<m_name<<")"<< endl;
}
~BB() {
cout << "调用了BB的析构函数("<<m_name<<")"<< endl;
}
};
int main() {
shared_ptr<AA>pa = make_shared<AA>("测试AA");
shared_ptr<BB>pb = make_shared<BB>("测试BB");
pa->m_p = pb;
pb->m_p = pa;
return 0;
}
上述代码,AA的成员引用BB的对象指针,BB的成员引用AA的对象指针,造成循环引用,此时单纯使用make_shared,就只会执行构造函数,而不会释放资源,执行析构函数。

引入weak_ptr
weak_ptr是为了配合shared_ptr而引入的,它指向一个由shared_ptr管理的资源,但不影响资源的生命周期,也就是说,将一个weak_ptr绑定到一个shared_ptr,不会改变shared_ptr的引用计数
将上述AA和BB中的引用,分别使用weak_ptr
#include <iostream>
#include <memory>
#include<string>
using namespace std;
class BB;
class AA {
public:
string m_name;
weak_ptr<BB> m_p;
AA() {
cout << m_name << "调用了AA的构造函数"<< endl;
}
AA(const string &name):m_name(name) {
cout << "调用了AA的构造函数("<<m_name<<")"<< endl;
}
~AA() {
cout << "调用了AA的析构函数("<<m_name<<")"<< endl;
}
};
class BB {
public:
string m_name;
weak_ptr<AA> m_p;
BB() {
cout << m_name << "调用了BB的构造函数"<< endl;
}
BB(const string &name):m_name(name) {
cout << "调用了BB的构造函数("<<m_name<<")"<< endl;
}
~BB() {
cout << "调用了BB的析构函数("<<m_name<<")"<< endl;
}
};
int main() {
shared_ptr<AA>pa = make_shared<AA>("测试AA");
shared_ptr<BB>pb = make_shared<BB>("测试BB");
pa->m_p = pb;
pb->m_p = pa;
return 0;
}

weak_ptr不会影响到shared_ptr的引用计数
int main() {
shared_ptr<AA>pa = make_shared<AA>("测试AA");
shared_ptr<BB>pb = make_shared<BB>("测试BB");
cout << "pa.usecount() = "<<pa.use_count() << endl;
cout << "pb.usecount() = "<<pa.use_count() << endl;
pa->m_p = pb;
pb->m_p = pa;
cout << "pa.usecount() = "<<pa.use_count() << endl;
cout << "pb.usecount() = "<<pa.use_count() << endl;
return 0;
}

weak_ptr使用
- weak_ptr没有重载-> 和 *操作符,不能直接访问资源
- 成员函数:
operator=() 把 shared_ptr或者weak_ptr赋值给weak_ptr
expired() 判断它指的资源是否过期
lock() 返回shared_ptr,如果资源已经过期,返回空的shared_ptr
reset() 将当前weak_ptr指针置为空
swap() 交换
int main() {
shared_ptr<AA>pa = make_shared<AA>("测试AA");
{
shared_ptr<BB>pb = make_shared<BB>("测试BB");
pa->m_p = pb;
pb->m_p = pa;
shared_ptr<BB> pp = pa->m_p.lock();
if (pp == nullptr)
{
cout << "语句块内部,pa->m_p已经过期" << endl;
} else {
cout << "语句块内部,pa->m_p没有过期 " << pp->m_name << endl;
}
}
shared_ptr<BB> pp = pa->m_p.lock();
if (pp == nullptr)
{
cout << "语句块外部,pa->m_p已经过期" << endl;
} else {
cout << "语句块外部,pa->m_p没有过期 " << pp->m_name << endl;
}
return 0;
}

网友评论