本小节回顾学习的知识点分别是weak_ptr常用的概述、常用操作、尺寸等问题。
今天总结的知识分为以下3个大点:
(1)weak_ptr概述
(1.1)weak_ptr的创建
(2)weak_ptr的常用操作
(2.1)use_count()
(2.2)expired()
(2.3)reset()
(2.4)lock()
(3)尺寸问题
(1)weak_ptr概述:
weak_ptr:“弱共享”/“弱引用”,作用:监视shared_ptr(强引用)的生命周期/用以辅助shared_ptr进行工作的!(人话:weak_ptr可以监视到它所指向的对象是否还存在!)
weak“弱”,反义词“强”。弱指的是weak_ptr,而强指的是shared_ptr。这里的弱就弱在weak_ptr控制不了所指向对象的生存期。且weak_ptr不是一种独立的智能指针,它依赖于shared_ptr而存在!。
解释:weak_ptr也是一个类模板,也是一个智能指针。这个weak_ptr智能指针是指向一个由shared_ptr管理的对象的!但是,这个weak_ptr智能指针是不控制所指向对象的生命周期的!
换句话说:将weak_ptr绑定到shared_ptr所指向的对象时并不会改变shared_ptr的引用计数!
注意①:weak_ptr的构造和析构是不会增加或减少shared_ptr所指向对象的引用计数的!但是“弱”引用计数会改变,也即改变weak_ptr的引用计数!!!
注意②:当shared_ptr所指向的对象的引用计数从1-》0时,需要释放其所指向的对象,那么不论是否有别的weak_ptr指向该对象,都会正常让shared_ptr释放其所指向的对象。
注意③:只有强(也既shared_ptr的)引用计数才会影响对象的生命周期,弱(也既weak_ptr的)引用计数是不会影响对象的生命周期的!
(1.1)weak_ptr的创建:
请看以下的代码:
shared_ptr<int> sp = make_shared<int>(1);//创建一个shared_ptr指针
weak_ptr<int> wp(sp);//用shared_ptr来初始化weak_ptr
(2)weak_ptr的常用操作
(2.1).use_count():
.use_count()方法的功能是:用以获取与其共享的所指向对象的其他shared_ptr指针的数量,或者说获取当前“强引用”所管理的资源的引用计数的个数。
请看以下的代码:
auto pi = make_shared<int>(111);
auto pi2(pi);//pi2是一个shared_ptr
weak_ptr<int> piw(pi);
int n = piw.use_count();
cout << "n = " << n << endl;
运行结果:
(2.2).expired():
.expired()方法的功能是:用来判断所观测到资源是否已经被释放了(即判断.use_count()方法是否为0,为0就表示该强引用所指向对象就不存在了,过期了;否则就表示还没过期,也即强引用所指向的对象还存在~)过期,返回true;未过期,返回false;
请看以下的代码:
auto pi = make_shared<int>(111);
auto pi2(pi);//pi2是一个shared_ptr
weak_ptr<int> piw(pi);
int n = piw.use_count();
cout << "n = " << n << endl;
pi.reset();
pi2.reset();
if (piw.expired()) {
cout << "该weak_ptr所指向的资源已经被释放了!" << endl;
}
运行结果:
(2.3).reset():
.reset()方法的功能是:在弱引用weak_ptr中,.reset()方法的作用是将该弱引用指针设置为空nullptr,但不影响指向该对象的强引用数量,只会使得其弱引用数量减少。
请看以下的代码:
auto pi = make_shared<int>(111);
auto pi2(pi);//pi2是一个shared_ptr
weak_ptr<int> piw(pi);
weak_ptr<int> piw2(pi);
piw.reset();
piw2.reset();
运行结果:
在执行piw.reset()这行代码前的运行结果:
在执行了piw.reset()这行代码后的运行结果:
在执行了piw2.reset()这行代码后的运行结果:
可见,weak_ptr智能指针的.reset()方法会使得弱引用次数减少,但是不会影响强引用次数。
(2.4).lock():
.lock()方法的功能是:判断weak_ptr所指向的shared_ptr对象是否存在。若存在,则这个lock方法会返回一个指向该对象的shared_ptr指针;若它所指向的这个shared_ptr对象不存在,则lock()函数会返回一个空的shared_ptr。
请看以下代码:
auto p1 = make_shared<int>(42);
weak_ptr<int> pw;
pw = p1;//用shared_ptr给weak_ptr赋值
if (!pw.expired()) {
auto p2 = pw.lock();//.lock()方法返回一个shared_ptr,并且此时强引用计数为2
if (p2) {
//p2非空,表明pw所指向的shared_ptr所管理的对象此时没有expire
cout << "p2还在呢!" << endl;
}
else {
cout << "p2不在了呢!" << endl;
}
}
(3)尺寸(占用的内存空间)问题:
weak_ptr的尺寸和shared_ptr的尺寸是一样大的,都是裸指针的2倍。且他们都有2种指针,一个都指向T类型的对象,另一个都指向同一个控制块!
它们的第一个指针都指向某类型的对象,第二个指针都指向一个很大的数据类型:控制块。这个控制块含有:
1---所指向对象的强引用计数
2---所指向对象的弱引用计数
3---其他data:比如自定义的删除器指针等等
请看以下代码:
weak_ptr<int> pw;
int a = 1;
int* p = &a;
cout << sizeof(p) << endl;//8字节
cout << sizeof(pw) << endl;//16字节 = 2 * 8 字节
以上就是我总结的关于weak_ptr常用的概述、常用操作、尺寸等问题的笔记。希望你能读懂并且消化完,也希望自己能牢记这些小小的细节知识点,加油吧,我们都在coding的路上~