类中使用shared_ptr()的问题
当我们先定义一个指针,然后再用这个指针构造两个智能指针
int main()
{
int* pt = new int();
std::shared_ptr<int> p1(pt);
std::shared_ptr<int> p2(pt);
std::cout << "p1.use_count() = " << p1.use_count() << std::endl;
std::cout << "p2.use_count() = " << p2.use_count() << std::endl;
return 0;
}
运行后就会报错,显示的是pt指针被重复释放了
原因是p1和p2都以为自己是唯一独占pt的智能指针,不知道还有智能指针指向pt
所以输出后发现两个引用计数都是1
如果需要不报错,就得这样写
shared_ptr<int> p2 = p1
通过p1来定义p2,它们就知道pt有两个智能指针了,就不会报错。
再来看一个代码
class client
{
public:
~client()
{
std::cout << "~client()\n";
}
};
int main()
{
client* cp = new client();
std::shared_ptr<client> csp1(cp);
std::shared_ptr<client> csp2(cp);
std::cout << "csp1.use_count: " << csp1.use_count() << std::endl;
std::cout << "csp2.use_count: " << csp2.use_count() << std::endl;
return 0;
}
这个报的一样的错,原理相同,问题是我们实际开发中,很多时候需要通过this指针来获取对象的内容
这个时候需要通过enable_shared_from_this来解决问题
enable_shared_from_this的使用
class client : public std::enable_shared_from_this<client>
{
public:
~client()
{
std::cout << "~client()\n";
}
std::shared_ptr<client> get_ptr()
{
return shared_from_this();
}
};
int main()
{
client* cp = new client();
std::shared_ptr<client> csp1(cp);
std::shared_ptr<client> csp2 = cp->get_ptr();
std::cout << "csp1.use_count: " << csp1.use_count() << std::endl;
std::cout << "csp2.use_count: " << csp2.use_count() << std::endl;
return 0;
}
将代码改写成这样,先公有继承这个模板类。
这里需要注意,在你通过shared_from_this()返回一个类的shared_ptr时,该对象必须已经被一个shared_ptr所管理,所以你不能直接csp2 = cp->get_ptr()
,要在此之前先有csp1(cp)
。
这样的话,借助shared_from_this(),可以使得该对象只要引用计数不为零,就任意获取它的一个shared_ptr。只要还有shared_ptr持有它,它就不会消亡。
实际开发中应用,以一个服务器demo举例
首先看下面一段代码
struct client : std::enable_shared_from_this<client>
{
public:
void start()
{
}
//...其他函数
}
void start()
{
std::shared_ptr<client> s = std::make_shared<client>();
s->start();
}
int main()
{
start();
return 0;
}
这里用make_shared初始化了一个client的shared_ptr,make_shared会让对象和控制块可以安全地存储在连续的内存块中。它简化了内存管理,并提高了性能。但是不支持自己写删除器。
start是一个初始的函数,里面会稍后添加业务,下面我们写一个定时器。
public:
void start()
{
start_up();
}
private:
void start_up()
{
_timer.expires_from_now(std::chrono::seconds(10));
_timer.async_wait(std::bind(&client::time_out, shared_from_this()));
}
void time_out()
{
start_up();
}
private:
boost::asio::steady_timer _timer;
在类里面这样设计定时器,当start()调用的时候,会调用start_up()函数设置一个定时器,并且注册time_out()这个回调函数。
此时start()函数调用结束了,临时变量s的智能指针也已经释放,但是,定时器内通过调用shared_from_this(),返回了一个s管理的对象的shared_ptr给async_wait里的回调time_out()中,s管理的对象并未消亡,直到运行完回调time_out(),它才会消亡,但是回调里面如果继续调用start_up()重新设定计时器,便又会返回一个该对象的shared_ptr()传入新注册的回调time_out()内,以此类推,只要计时器不关闭,永远不会消亡。
基于这一点,可以和读写搭配起来,灵活控制当前类在什么条件下保活,什么条件下析构。
1.本站内容仅供参考,不作为任何法律依据。用户在使用本站内容时,应自行判断其真实性、准确性和完整性,并承担相应风险。
2.本站部分内容来源于互联网,仅用于交流学习研究知识,若侵犯了您的合法权益,请及时邮件或站内私信与本站联系,我们将尽快予以处理。
3.本文采用知识共享 署名4.0国际许可协议 [BY-NC-SA] 进行授权
4.根据《计算机软件保护条例》第十七条规定“为了学习和研究软件内含的设计思想和原理,通过安装、显示、传输或者存储软件等方式使用软件的,可以不经软件著作权人许可,不向其支付报酬。”您需知晓本站所有内容资源均来源于网络,仅供用户交流学习与研究使用,版权归属原版权方所有,版权争议与本站无关,用户本人下载后不能用作商业或非法用途,需在24个小时之内从您的电脑中彻底删除上述内容,否则后果均由用户承担责任;如果您访问和下载此文件,表示您同意只将此文件用于参考、学习而非其他用途,否则一切后果请您自行承担,如果您喜欢该程序,请支持正版软件,购买注册,得到更好的正版服务。
5.本站是非经营性个人站点,所有软件信息均来自网络,所有资源仅供学习参考研究目的,并不贩卖软件,不存在任何商业目的及用途
暂无评论内容