智能指针reset()方法分析
reset()函数接受一个可选参数,这个参数可以是一个指向新对象的指针,也可以是一个空指针。
当参数为空指针时,reset()会释放原来指针所管理的资源,同时将指针置为空。当参数为非空指针时,
reset()会先释放原来指针所管理的资源,然后将指针重新指向新对象,
此时此刻,如果有其它智能指针也指向它,只是计数减一。
当使用reset函数时,智能指针的引用计数会相应地减少1。如果减少后引用计数变为0,则表示该资源不再被使用,可以安全地删除资源。
可以通过下面的代码去调试理解:
#include <iostream>
#include <functional>
#include <memory>
#include <thread>
class A{
public:
A(int x) : _x(x){
std::cout << " create " << _x << std::endl;
}
~A(){
std::cout << " release " << _x << std::endl;
}
int _x;
};
void testshared_ptr_Reset(){
std::shared_ptr<A> p(new A(1)); // 这里create A(1)
std::cout << p.use_count() << " p.get() = " << p.get() << __LINE__ << std::endl;
std::cout << p.get() << " " << __LINE__ << std::endl;
auto p2 = p;
auto p21 = p;
std::cout << p.use_count() << " " << __LINE__ << std::endl;
p.reset();
p.reset();
p.reset(); //多次reset,A(1)的引用次数只减少了1,
std::cout << p2.use_count() << " << p2.get() = " << p2.get() << __LINE__ << std::endl; // p2.get() == p1.get()
auto p3 = p;
std::cout << p.use_count() << " " << __LINE__ << std::endl;
std::cout << p3.use_count() << " " << __LINE__ << std::endl;
auto p4 = p;
std::cout << p.use_count() << " " << __LINE__ << std::endl;
p.reset(new A(2)); // 这里create A2
std::cout << p.use_count() << " " << __LINE__ << std::endl;
std::cout << p3.use_count() << " " << __LINE__ << std::endl;
// 退出的时候释放两次实例 A2 A1
}
智能指针循环引用
这是不推荐的,不要同时你中有我,我中有你,即:A的成员智能指针指向B,B的成员智能指针指向A
相互持有的时候,两边的析构函数都没有被调用到,造成内存泄漏。
这时候可以同weak_ptr来解决,它指向智能指针sp,但是并不持有引用计数,即sp的use_count()不会增加。
weak_ptr用法
接续前面的代码,weak_ptr的 lock, expired, use_count 三个函数了解它
weak_ptr调试的代码
std::weak_ptr<A> gw;
void TestWeakPtr(){
gw.lock();
std::this_thread::sleep_for(std::chrono::seconds(5));
if(gw.expired()){
std::cout << "wb lock gp success !" << std::endl;
} else {
std::cout << "wb lock gp failed !" << std::endl;
}
}
int main(){
std::shared_ptr<A> sp(new A(3));
gw = sp;
std::cout << " gw.use_count() = " << gw.use_count() << " sp.use_count() = " << sp.use_count() << std::endl;
std::thread ([&](){
std::this_thread::sleep_for(std::chrono::seconds(1));
std::cout << " sp reset \n";
sp.reset();
}).detach();
TestWeakPtr(); // 测试A(3)的资源使用情况
std::cout << " gw.use_count() = " << gw.use_count() << " sp.use_count() = " << sp.use_count() << std::endl;
return 0;
}
输出:
create 3
gw.use_count() = 1 sp.use_count() = 1 //增加了gw对sp的应用,但是sp的use_count()没有增加
sp reset
release 3
wb lock gp success !
gw.use_count() = 0 sp.use_count() = 0