C++ weak_ptr的使用
发布时间:2022-10-14 21:36:09 247
相关标签: # c++# ios
这是一篇关于讲解关于weak_ptr使用的问题,在c++11被引入,weak_ptr也是c++11智能指针的一种,是为了解决shared_ptr循环引用的问题而引入。
1. 循环引用导致的问题
循环引用,简单来说就是:两个对象互相使用一个shared_ptr成员变量指向对方的会造成循环引用,导致引用计数失效。
#include
#include
class classB;
class classA {
public:
classA() {
std::cout << "classA()" << std::endl;
}
~classA() {
std::cout << "~classA()" << std::endl;
}
void set_ptr(std::shared_ptr& ptr) {
std::cout << "在类A中,拷贝之前m_ptr_b的引用次数为" << m_ptr_b.use_count() << std::endl;
m_ptr_b = ptr;
std::cout << "在类A中,拷贝之后m_ptr_b的引用次数为" << m_ptr_b.use_count() << std::endl;
}
private:
std::shared_ptr m_ptr_b;
};
class classB {
public:
classB() {
std::cout << "classB()" << std::endl;
}
~classB() {
std::cout << "~classB()" << std::endl;
}
void set_ptr(std::shared_ptr& ptr) {
std::cout << "在类B中,拷贝之前m_ptr_a的引用次数为" << m_ptr_a.use_count() << std::endl;
m_ptr_a = ptr;
std::cout << "在类B中,拷贝之后m_ptr_a的引用次数为" << m_ptr_a.use_count() << std::endl;
}
private:
std::shared_ptr m_ptr_a;
};
int main()
{
std::shared_ptr ptr_a(new classA()); //调用类A构造函数,此时ptr_a的引用计数已经加1
std::cout << "new 完之后 ptr_a的引用计数为" << ptr_a.use_count() << std::endl;
std::shared_ptr ptr_b(new classB()); //调用类B构造函数,此时ptr_b的引用计数已经加1
std::cout << "new 完之后 ptr_b的引用计数为" << ptr_b.use_count() << std::endl;
ptr_a->set_ptr(ptr_b); //set内部会发生拷贝动作,导致智能指针的引用计数加1,
ptr_b->set_ptr(ptr_a);
std::cout << ptr_a.use_count() << " " << ptr_b.use_count() << std::endl;
system("pause");
return 0;
}
可以看到,上述代码执行完之后,没有执行类A和类B的析构函数。与代码分析类似,由于引用计数的值在退出main函数之前没有减到1,因此也没执行对象的析构函数。
2.使用weak_ptr解决循环引用不析构的问题
将上述代码中类A和类B成员中的智能指针换为weak_ptr可以解决,如下代码
#include
#include
class classB;
class classA {
public:
classA() {
std::cout << "classA()" << std::endl;
}
~classA() {
std::cout << "~classA()" << std::endl;
}
void set_ptr(std::shared_ptr& ptr) {
std::cout << "在类A中,拷贝之前m_ptr_b的引用次数为" << m_ptr_b.use_count() << std::endl;
m_ptr_b = ptr;
std::cout << "在类A中,拷贝之后m_ptr_b的引用次数为" << m_ptr_b.use_count() << std::endl;
}
private:
std::weak_ptr m_ptr_b;
};
class classB {
public:
classB() {
std::cout << "classB()" << std::endl;
}
~classB() {
std::cout << "~classB()" << std::endl;
}
void set_ptr(std::shared_ptr& ptr) {
std::cout << "在类B中,拷贝之前m_ptr_a的引用次数为" << m_ptr_a.use_count() << std::endl;
m_ptr_a = ptr;
std::cout << "在类B中,拷贝之后m_ptr_a的引用次数为" << m_ptr_a.use_count() << std::endl;
}
private:
std::weak_ptr m_ptr_a;
};
int main()
{
std::shared_ptr ptr_a(new classA()); //调用类A构造函数,此时ptr_a的引用计数已经加1
std::cout << "new 完之后 ptr_a的引用计数为" << ptr_a.use_count() << std::endl;
std::shared_ptr ptr_b(new classB()); //调用类B构造函数,此时ptr_b的引用计数已经加1
std::cout << "new 完之后 ptr_b的引用计数为" << ptr_b.use_count() << std::endl;
ptr_a->set_ptr(ptr_b); //set内部会发生拷贝动作,导致智能指针的引用计数加1,
ptr_b->set_ptr(ptr_a);
std::cout << ptr_a.use_count() << " " << ptr_b.use_count() << std::endl;
system("pause");
return 0;
}
- [] 使用weak_ptr建立的引用不会导致引用计数的增加
3.weak_ptr的原理
weak_ptr只是指向shared_ptr对象的一个指针,它可以从一个shared_ptr或者weak_ptr构造而来,但是weak_ptr的构造和析构不会引起shared_ptr的引用计数的增减。weak_ptr是shared_ptr的一个助手。
4.使用weak_ptr需要注意
weak_ptr并不改变其所共享的shared_ptr实例的引用计数,可能存在weak_ptr指向的对象被释放掉这种情况。这时,就不能使用weak_ptr直接访问对象。那么如何判断weak_ptr指向对象是否存在呢?C++中提供了lock函数来实现该功能。如果对象存在,lock()函数返回一个指向共享对象的shared_ptr(引用计数会增1),否则返回一个空shared_ptr。weak_ptr还提供了expired()函数来判断所指对象是否已经被销毁.
文章来源: https://blog.51cto.com/u_13030942/5424760
特别声明:以上内容(图片及文字)均为互联网收集或者用户上传发布,本站仅提供信息存储服务!如有侵权或有涉及法律问题请联系我们。
举报