做soho的网站线上推广是什么意思
弱引用智能指针 std::weak_ptr 可以看做是shared_ptr的助手,它不管理 shared_ptr 内部的指针。std::weak_ptr 没有重载操作符*和->,因为它不共享指针,
不能操作资源,所以它的构造不会增加引用计数,析构也不会减少引用计数,它的主要作用就是作为一个旁观者监视shared_ptr 中管理的资源是否存在.
初始化
#include<iostream>
#include<memory>
using namespace std;int main(){shared_ptr<int> sp(new int);//weak_ptr<int> wp1;//空weak_ptr对象weak_ptr<int> wp2(wp1);//也是空weak_ptr<int> wp3(sp);//通过shared_ptr对象构造一个可用的weak_ptr实例对象,就是wp3监管spweak_ptr<int> wp4;wp4=sp;//通过shared_ptr对象构造一个可用的weak_ptr实例对象(这是一个隐式类型转换),给赋值运算符重载了weak_ptr<int> wp5;wp5=wp3;//通过weak_ptr对象构造一个可用的weak_ptr实例对象,给赋值运算符重载了
}
use_count()
通过调用weak_ptr类提供的use_count()方法可以获得当前观测资源的引用计数
#include<iostream>
#include<memory>
using namespace std;
int main() {
shared_ptr<int> sp(new int);
weak_ptr<int> wp1;
weak_ptr<int> wp2(wp1);
weak_ptr<int> wp3(sp);
weak_ptr<int> wp4;
wp4 = sp;
weak_ptr<int> wp5;
wp5 = wp3;
cout << wp1.use_count() << endl;
cout << wp2.use_count() << endl;
cout << wp3.use_count() << endl;
cout << wp4.use_count() << endl;
cout << wp5.use_count() << endl;
}/*运行结果:
0
0
1
1
1*/
通过打印的结果可以知道,虽然弱引用智能指针 wp3、wp4、wp5 监测的资源是同一个,但是它的引用计数并没有发生任何的变化,也进一步证明了 weak_ptr 只是监测资源,并不管理资源。
expired()(失效的)
通过调用 std::weak_ptr 类提供的 expired()方法来判断观测的资源是否已经被释放
#include<iostream>
#include<memory>
using namespace std;
int main() {
shared_ptr<int> shared(new int(10));
weak_ptr<int> weak(shared);
cout << weak.expired() << endl;
shared.reset();
cout << weak.expired() << endl;return 0;
}
/*运行结果:
0
1*/
weak_ptr监测的就是shared_ptr管理的资源,当共享智能指针调用 shared.reset();之后管理的资源被释放,因此 weak.expired()函数的结果返回 true,表示监测的资源已经不存在了。
lock()
通过调用weak_ptr类提供的lock()方法来获取管理所监测资源的shared_ptr对象
#include<iostream>
#include<memory>
using namespace std;
int main() {
shared_ptr<int> sp1, sp2;
weak_ptr<int> wp;
sp1 = make_shared<int>(520);
wp = sp1;
sp2 = wp.lock();
cout << wp.use_count() << endl;
sp1.reset();
cout << wp.use_count() << endl;
sp1 = wp.lock();
cout << wp.use_count() << endl;cout << *sp1 << endl;
cout << *sp2 << endl;return 0;
}/*运行结果:
2
1
2
520
520*/
sp2 = wp.lock();通过调用 lock()方法得到一个用于管理 weak_ptr 对象所监测的资源的共享智能指针对象,使用这个对象初始化 sp2,此时所监测资源的引用计数为 2.
sp1.reset();共亨智能指针 sp1 被重置,weak_ptr 对象所监测的资源的引用计数减 1
sp1 = wp.lock();sp1 重新被初始化,并且管理的还是 weak_ptr 对象所监测的资源,因此引用计数加 1.
共享智能指针对象 sp1 和 sp2 管理的是同一块内存,因此最终打印的内存中的结果是相同的,都是 520.
reset()
通过调用 std::weak_ptr 类提供的 reset()方法来清空对象,使其不监测任何资源。
#include<iostream>
#include<memory>
using namespace std;
int main() {
shared_ptr<int> sp(new int(10));
weak_ptr<int> wp(sp);
cout << wp.expired() << endl;
wp.reset();
cout << wp.expired() << endl;
cout << sp.use_count() << endl;return 0;
}/*运行结果:
0
1
1*/
返回管理this的shared_ptr
#include<iostream>
#include<memory>
using namespace std;struct Test
{shared_ptr<Test> getSharedPtr(){return shared_ptr<Test>(this); }~Test(){cout<<"析构函数"<<endl; }
};
int main()
{shared_ptr<Test> sp1(new Test);cout<<"引用个数"<<sp1.use_count()<<endl;shared_ptr<Test> sp2=sp1->getSharedPtr();cout<<"引用个数"<<sp1.use_count()<<endl;return 0;
}
当用Test的对象初始化sp1时,sp1指向这个对象,当sp1调用getSharedPtr函数时,要给隐含参数this传值,传的就是Test对象的原始地址,这就会导致用原始地址初始化多次智能指针,这俩智能指针各自维护着自己的引用计数,当一个引用计数为0时,就会释放那块空间,而另一个指针不知道那块空间被释放,会再次释放那块空间,导致二次释放问题
通过输出的结果可以看到一个对象被析构了两次,其原因是这样的:在这个例子中使用同一个指针 this 构造了两个智能指针对象 sp1 和 sp2,这二者之间是没有任何关系的,因为 sp2 并不是通过 sp1 初始化得到的实例对象。在离开作用域之后 this 将被构造的两个智能指针各自析构导致重复析构的错误。
循环引用
#include<iostream>
#include<memory>
using namespace std;class A;
class B;
class A{
public:shared_ptr<B> bptr;~A(){cout<<"A的析构"<<endl; }
};
class B{
public:shared_ptr<A> aptr;~B(){cout<<"B的析构"<<endl; }
};
void testPtr(){shared_ptr<A> ap(new A);shared_ptr<B> bp(new B);cout<<"A的引用计数:"<<ap.use_count()<<endl;cout<<"B的引用计数:"<<bp.use_count()<<endl;ap->bptr=bp;bp->aptr=ap;cout<<"A的引用计数:"<<ap.use_count()<<endl;cout<<"B的引用计数:"<<bp.use_count()<<endl;
}
int main(){testPtr();return 0;
}
当作用域结束,想要释放A对象,就得让A对象里面的bptr引用计数为0,但是aptr指向的是B,只有B没有,bptr引用计数才为0,但是B里有个aptr,只有aptr引用计数为0,B才能没,但是aptr指向的是A,只有A没了,aptr才能没,这就导致,两边都没不了,ap和bp引用计数都不为0
要解决这个循环引用问题,可以考虑使用weak_ptr(弱指针)来打破循环引用,例如将类A中的shared_ptr改为weak_ptr,类B中的shared_ptr改为weak_ptr,这样就可以在需要访问对方对象时通过weak_ptr的lock方法来获取有效的shared_ptr,同时又不会造成循环引用导致的析构函数无法调用的问题。