前言
weak_ptr并不拥有指针的所有权,因此并不能调用->和解引用。
那为什么要使用weak_ptr呢?
如果A类中有一个需求需要存储其他A类对象的信息,如果使用shared_ptr,那么在销毁时会遇到循环依赖的问题,所以我们这里需要用一个不需要拥有所有权的指针来标记该同类对象,weak_ptr可以通过lock()函数来提升为shared_ptr(类型对象)。
提示:以下是本篇文章正文内容,下面案例可供参考
一、weak_ptr不能解引用
二、weak_ptr的使用
使用weak_ptr并不会使引用计数值+1,lock函数可以使weak_ptr转换为shared_ptr。
#include<iostream>
#include<memory>
#include"cat.h"
using namespace std;
int main(int argc, char *argv[])
{
std::shared_ptr<Cat> s_p_c1=std::make_shared<Cat>("C1");
std::weak_ptr w_p_c1(s_p_c1);
//use_count()
cout<<"w_p_c1:"<<w_p_c1.use_count()<<endl;
cout<<"s_p_c1:"<<s_p_c1.use_count()<<endl;
//w_p_c1->cat_info();
std::shared_ptr<Cat> s_p_c2=w_p_c1.lock();
cout<<"w_p_c1:"<<w_p_c1.use_count()<<endl;
cout<<"s_p_c1:"<<s_p_c1.use_count()<<endl;
cout<<"s_p_c2:"<<s_p_c2.use_count()<<endl;
cout<<"----- yz -----"<<endl;
return 0;
}
运行结果:
三、用shared_ptr产生环形引用问题
1.在这里需要对cat.h稍微修改一下(main.cpp, cat.h, cat.cpp在unique_ptr的使用一文中有提到)
#ifndef CAT_H
#define CAT_H
#include<string>
#include<iostream>
#include<memory>
class Cat
{
public:
Cat(std::string name);
Cat()=default;
~Cat();
void cat_info() const
{
std::cout<<"cat info name:"<<name<<std::endl;
}
std::string get_name() const
{
return name;
}
void set_cat_name(const std::string &name)
{
this->name=name;
}
void set_friend(std::shared_ptr<Cat> c)
{
m_friend=c;//这里改
}
private:
std::string name{"Mimi"};
std::shared_ptr<Cat> m_friend;//这里改
};
#endif
主函数:
#include<iostream>
#include<memory>
#include"cat.h"
using namespace std;
int main(int argc, char *argv[])
{
// std::shared_ptr<Cat> s_p_c1=std::make_shared<Cat>("C1");
std::shared_ptr<Cat> c3=std::make_shared<Cat>("C3");
std::shared_ptr<Cat> c4=std::make_shared<Cat>("C4");
c3->set_friend(c4);
c4->set_friend(c3);
cout<<"----- yz -----"<<endl;
return 0;
}
实验结果:
结论:上面的c3和c4在程序运行结束后并没有被销毁。
下面的实验来验证是环形引用的问题导致对象不能销毁:将12、13行注释:
#include<iostream>
#include<memory>
#include"cat.h"
using namespace std;
int main(int argc, char *argv[])
{
// std::shared_ptr<Cat> s_p_c1=std::make_shared<Cat>("C1");
std::shared_ptr<Cat> c3=std::make_shared<Cat>("C3");
std::shared_ptr<Cat> c4=std::make_shared<Cat>("C4");
// c3->set_friend(c4);
// c4->set_friend(c3);
cout<<"----- yz -----"<<endl;
return 0;
}
实验结果:
结论:将那两行注释之后,程序运行结束后,c3和c4销毁,说明是环形引用造成的问题。
2.使用weak_ptr解决环形引用的问题
修改cat.h文件:
#ifndef CAT_H
#define CAT_H
#include<string>
#include<iostream>
#include<memory>
class Cat
{
public:
Cat(std::string name);
Cat()=default;
~Cat();
void cat_info() const
{
std::cout<<"cat info name:"<<name<<std::endl;
}
std::string get_name() const
{
return name;
}
void set_cat_name(const std::string &name)
{
this->name=name;
}
void set_friend(std::shared_ptr<Cat> c)//这里不用改
{
m_friend=c;
}
private:
std::string name{"Mimi"};
std::weak_ptr<Cat> m_friend;//原来是std::shared_ptr<Cat> m_friend;
};
#endif
再次运行:
#include<iostream>
#include<memory>
#include"cat.h"
using namespace std;
int main(int argc, char *argv[])
{
std::shared_ptr<Cat> c3=std::make_shared<Cat>("C3");
std::shared_ptr<Cat> c4=std::make_shared<Cat>("C4");
c3->set_friend(c4);
c4->set_friend(c3);
cout<<"----- yz -----"<<endl;
return 0;
}
实验结果:
对象能够正常销毁。
总结
weak_ptr能够解决环形引用问题,是shared_ptr的补充。