1. 开篇

正式介绍weak_ptr之前,先来复习一下shared_ptr 的一些知识。
我们知道shared_ptr是采用引用计数的智能指针,多个shared_ptr实例可以指向同一个动态对象,并维护了一个共享的引用计数器。

对于引用计数法实现的计数,总是避免不了循环引用(或环形引用)的问题,shared_ptr也不例外。

示例

class Child;class Parent
{public:shared_ptr<Child> child;~Parent() { cout << "Bye Parent" << endl; }void hi() const { cout << "He1lo" << endl; }
};class Child
{public:shared_ptr<Parent> parent;~Child() { cout << "Bye Child" << endl; }
};int main()
{shared_ptr<Parent> parent = make_shared<Parent>();shared_ptr<Child> child = make_shared<Child>();parent->child = child;child->parent = parent;child- >parent->hi();return 0;
}

运行结果

上面代码的运行结果,只打印出”Hello”,而并没有打印出"Bye Parent"或"Bye Child",说明Parent和Child的析构函数并没有调用到。这是因为Parent和Child对象内部,具有各自指向对方的shared_ptr,加上parent和child这两个shared_ptr,说明每个对象的引用计数都是2。当程序退出时,即使parent和child被销毁,也仅仅是导致引用计数变为了1,因此并未销毁arent和Child对象。

parent->child = child;
child->parent = parent;


为了解决类似这样的问题,C++11引入了weak_ptr,来打破这种循环引用。

2. weak_ptr的概念

weak_ptr是为了配合shared_ptr而引入的一种智能指针,它指向一个由 shared_ptr管理的对象而不影响所指对象的生命周期,也就是将一个weak_ptr绑定到一个shared_ptr不会改变shared_ptr的引用计数。

不论是否有weak_ptr指向,一旦最后一个指向对象的shared_ptr被销毁,对象就会被释放。

从这个角度看,weak_ptr更像是shared_ptr的一个助手而不是智能指针。

3. weak_ptr的使用

3.1 如何创建weak_ptr实例

当我们创建一个weak_ptr时,需要用一个shared_ptr实例来初始化 weak_ptr,由于是弱共享,weak_ptr的创建并不会影响shared_ptr的引用计数值。

int main()
{shared_ptr<int> sp(new int(5));cout <<"创建前sp的引用计数:" << sp.use_count() << endl;   //use_count = 1weak_ptr<int> wp(sp);cout <<"创建后sp的引用计数: " << sp.use_count() << endl; //use_count = 1return 0;
}

3.2 如何判断weak_ptr指向对象是否存在

既然weak_ptr并不改变其所共享的shared_ptr实例的引用计数,那就可能存在weak_ptr指向的对象被释放掉这种情况。

这时,我们就不能使用weak_ptr直接访问对象。那么我们如何判断weak_ptr指向对象是否存在呢?
C++中提供了lock函数来实现该功能。
如果对象存在,lock()函数返回一个指向共享对象的shared_ptr,否则返回一个空shared_ptr。

class Object
{private:int value;
public:object(int x = 0) :value(x) { cout << "object Constructor.. ." << endl; }~object() { cout << "object Destructor..." <<endl; }int Getvalue() const { return value; }
};
int main()
{shared_ptr<Object> sp(new Object(10));weak_ptr<Object> wp(sp);//sp.reset(); //??if (shared_ptr<Object> pa = wp.lock()){cout << pa->GetValue() << endl;}else{//weak_ptr还提供了expired()函数来判断所指对象是否已经被销毁cout << wp.expired() << endl;cout << "wp引用的对象为空" <<endl;}return 0;
}

3.3 如何使用weak_ptr

weak_ptr并没有重载operator->和operator*操作符,因此不可直接通过weak_ptr使用对象,典型的用法是调用其lock函数来获得shared_ptr示例,进而访问原始对象。

使用weak_ptr来改造最前面的代码,打破循环引用问题。

class Child;class Parent
{public:weak_ptr<Child> child; //~parent() { cout << "Bye Parent" <<endl; }void hi() const { cout<< "Hello" << endl; }
};class Child
{public:weak_ptr<Parent> parent;   //~Child() { cout << "Bye Child" << endl; }
};int main()
{shared_ptr<Parent> parent = make_shared<Parent>();shared_ptr<Child> child = make_shared<Child>();parent->child = child;child->parent = parent;//child->parent->hi(); //??if(child->expired()) { child->parent.lock()->hi();   }return 0;
}

智能指针——weak_ptr相关推荐

  1. 9.C++弱引用智能指针weak_ptr的用处

    weak_ptr也是一个引用计数型智能指针,但是它不增加对象的引用计数,即弱引用.与之相对,shared_ptr是强引用,只要有一个指向对象的shared_ptr存在,该对象就不会析构,直到指向对象的 ...

  2. 智能指针weak_ptr

    weak_ptr这个指针天生一副小弟的模样,也是在C++11的时候引入的标准库,它的出现完全是为了弥补它老大shared_ptr天生有缺陷的问题. 相比于上一代的智能指针auto_ptr来说,新进老大 ...

  3. Boost智能指针——weak_ptr

    循环引用: 引用计数是一种便利的内存管理机制,但它有一个很大的缺点,那就是不能管理循环引用的对象.一个简单的例子如下: #include <string> #include <ios ...

  4. 【Boost】boost库中智能指针——weak_ptr

    循环引用: 引用计数是一种便利的内存管理机制,但它有一个很大的缺点,那就是不能管理循环引用的对象.一个简单的例子如下: #include <string> #include <ios ...

  5. [C++11]弱引用智能指针weak_ptr初始化和相关的操作函数

    弱引用智能指针 std::weak_ptr 可以看做是 shared_ptr 的助手,它不管理 shared_ptr 内部的指针.std::weak_ptr 没有重载操作符 * 和 ->,因为它 ...

  6. C++11智能指针shared_ptr、weak_ptr、unique_ptr用法

    该博文为原创文章,未经博主同意不得转载,如同意转载请注明博文出处 本文章博客地址:https://cplusplus.blog.csdn.net/article/details/105065859 智 ...

  7. C++总结8——shared_ptr和weak_ptr智能指针

    http://blog.csdn.net/wendy_keeping/article/details/75268687 智能指针的提出:智能指针是存储指向动态分配对象指针的类,用于生存期控制.能够确保 ...

  8. c++几种智能指针比较

    unique_ptr持有对对象的独有权--两个unique_ptr不能指向一个对象,即 unique_ptr 不共享它所管理的对象.它无法复制到其他 unique_ptr,无法通过值传递到函数,也无法 ...

  9. C++11新特性之智能指针

    智能指针的特性 智能指针可以自动释放不再使用的内存,能够有效的防止内存泄漏. 智能指针是一个对象,普通指针是一个变量. 智能指针是对普通指针的封装,其安全性要高于直接使用普通指针. 智能指针的分类 共 ...

最新文章

  1. 腾讯云100亿元目标达成,发阳光普照奖iPhone 11 Pro,你酸了吗?
  2. 《iOS应用软件设计之道》—— 3.1 流向:从一个画面到另一个画面
  3. C语言获得数组长度的函数
  4. win7怎么去除快捷方式的小箭头
  5. 【基带传输】基于matlab的简易无线基带传输系统的仿真
  6. 89. Leetcode 96. 不同的二叉搜索树 (动态规划-基础题)
  7. 英语语法---感叹词详解
  8. 从IC设计来看Trace32的用途
  9. WPF数据驱动应用程序上具有通用Lambda表达式的筛选器模式
  10. MATLAB求解夏普利值
  11. 未来教育计算机二级office评分有问题,未来教育计算机二级-未来教育计算机二级msoffice题库评分 – 手机爱问...
  12. win10修改C盘Users底下的账号名字
  13. 【人工智能项目】sg2im文字转图像
  14. 2022年Google SEO基础知识,技术搜索引擎优化介绍
  15. 自己搭建开源数据统计报表系统
  16. 如何用Python制作一个简单的二维码生成器
  17. HUAWEI机试:最长的顺子
  18. 程序员:一个女生不主动联系你还有机会吗?
  19. apple 产品鉴定
  20. 各种图片格式(BMP,JPG, GIF,PNG, TGA) 简单介绍

热门文章

  1. Ubuntu 14.04.5 imx6 开发环境搭建
  2. 给JBoss种蛊分析
  3. bzoj1878: [SDOI2009]HH的项链
  4. 测试软件测试赢在测试2:中国软件测试专家访谈录
  5. 园子里有没有介绍netframework3.0的
  6. MVC架构在Asp.net中的应用和实现
  7. 4:如何实现对两个整数变量的值进行互换。
  8. msfvenom生成木马和内网穿透
  9. 【数据结构与算法】之深入解析“颜色分类”的求解思路与算法示例
  10. 336. Palindrome Pairs 回文对