C++11中weak_ptr的使用
在C++中,动态内存的管理是通过一对运算符来完成的:new,在动态内存中为对象分配空间并返回一个指向该对象的指针,可以选择对对象进行初始化;delete,接受一个动态对象的指针,销毁该对象,并释放与之关联的内存。
动态内存的使用很容易出问题,因为确保在正确的时间释放内存是极其困难的。有时会忘记释放内存,在这种情况下会产生内存泄露;有时在尚有指针引用内存的情况下就释放了它,在这种情况下就会产生引用非法内存的指针。
为了更容易(同时也更安全)地使用动态内存,C++11标准库提供了两种智能指针(smart pointer)类型来管理动态对象。智能指针的行为类似常规指针,重要的区别是它负责自动释放所指的对象。C++11标准库提供的这两种智能指针的区别在于管理底层指针的方式:shared_ptr允许多个指针指向同一个对象;unique_ptr则"独占"所指向的对象。C++11标准库还定义了一个名为weak_ptr的辅助类,它是一种弱引用,指向shared_ptr所管理的对象。这三种类型都定义在memory头文件中。智能指针是模板类而不是指针。类似vector,智能指针也是模板,当创建一个智能指针时,必须提供额外的信息即指针可以指向的类型。默认初始化的智能指针中保存着一个空指针。智能指针的使用方式与普通指针类似。解引用一个智能指针返回它指向的对象。如果在一个条件判断中使用智能指针,效果就是检测它是否为空。
Pointer misuse can be a major source of bugs. Smart pointers prevent most situations of memory leaks by making the memory deallocation automatic. More generally, they make object destruction automatic: an object controlled by a smart pointer is automatically destroyed (finalized and then deallocated) when the last (or only) owner of an object is destroyed.
In C++, a smart pointer is implemented as a template class that mimics, by means of operator overloading, the behaviors of a traditional (raw) pointer, while providing additional memory management features.
std::weak_ptr is a smart pointer that holds a non-owning ("weak") reference to an object that is managed by std::shared_ptr. It must be converted to std::shared_ptr in order to access the referenced object.
std::weak_ptr models temporary ownership: when an object needs to be accessed only if it exists, and it may be deleted at any time by someone else, std::weak_ptr is used to track the object, and it is converted to std::shared_ptr to assume temporary ownership. If the original std::shared_ptr is destroyed at this time,the object's lifetime is extended until the temporary std::shared_ptr is destroyed as well.
In addition,std::weak_ptr is used to break circular references of std::shared_ptr.
weak_ptr is primarily useful in the rare cases where it is needed in order to break'circular references' – a problem with the use of reference counting in shared_ptr.
Sometimes an object must store a way to access the underlying object of a shared_ptr without causing the reference count to be incremented. Typically, this situation occurs when you have cyclic references between shared_ptr instances. The best design is to avoid shared ownership of pointers whenever you can. However, if you must have shared ownership of shared_ptr instances, avoid cyclic references between them. When cyclic references are unavoidable, or even preferable for some reason, use weak_ptr to give one or more of the owners a weak reference to another shared_ptr. By using a weak_ptr, you can create a shared_ptr that joins to an existing set of related instances, but only if the underlying memory resource is still valid. A weak_ptr itself does not participate in the reference counting, and therefore, it cannot prevent the reference count from going to zero. However, you can use a weak_ptr to try to obtain a new copy of the shared_ptr with which it was initialized. If the memory has already been deleted, a bad_weak_ptr exception is thrown. If the memory is still valid, the new shared pointer increments the reference count and guarantees that the memory will be valid as long as the shared_ptr variable stays in scope.
weak_ptr被设计为与shared_ptr共同工作,可以从一个shared_ptr或者另一个weak_ptr对象构造,获得资源的观测权。但weak_ptr没有共享资源,它的构造不会引起指针引用计数的增加。同样,在weak_ptr析构时也不会导致引用计数的减少,它只是一个静静地观察者。weak_ptr没有重载operator*和->,这是特意的,因为它不共享指针,不能操作资源,这是它弱的原因。但它可以使用一个非常重要的成员函数lock()从被观测的shared_ptr获得一个可用的shared_ptr对象,从而操作资源。
weak_ptr用于解决”引用计数”模型循环依赖问题,weak_ptr指向一个对象,并不增减该对象的引用计数器。weak_ptr用于配合shared_ptr使用,并不影响动态对象的生命周期,即其存在与否并不影响对象的引用计数器。weak_ptr并没有重载operator->和operator *操作符,因此不可直接通过weak_ptr使用对象。weak_ptr提供了expired()与lock()成员函数,前者用于判断weak_ptr指向的对象是否已被销毁,后者返回其所指对象的shared_ptr智能指针(对象销毁时返回”空”shared_ptr)。
智能指针是模板类而不是指针.
weak_ptr并没有重载operator->和operator *操作符,因此不可直接通过weak_ptr使用对象,典型的用法是调用其lock函数来获得shared_ptr示例,进而访问原始对象。
weak_ptr是一种不控制所指向对象生存期的智能指针,它指向由一个shard_ptr管理的对象。将一个weak_ptr绑定到一个shared_ptr不会改变shared_ptr的引用计数。一旦最后一个指向对象的shared_ptr被销毁,对象就会被释放。即使有weak_ptr指向对象,对象也还是会被释放。
当创建一个weak_ptr时,要用一个shared_ptr来初始化它。不能使用weak_ptr直接访问对象,而必须调用lock。此函数检查weak_ptr指向的对象是否仍存在。如果存在,lock返回一个指向共享对象的shared_ptr。与任何其它shared_ptr类似,只要此shared_ptr存在,它所指向的底层对象也就会一直存在。
下图列出了weak_ptr支持的操作(来源于C++ Primer Fifth Edition 中文版):
#include "weak_ptr.hpp"
#include <iostream>
#include <memory>
#include <algorithm>
#include <string>
#include <vector>///
// reference: http://en.cppreference.com/w/cpp/memory/weak_ptr
std::weak_ptr<int> gw;void f()
{if (auto spt = gw.lock()) { // Has to be copied into a shared_ptr before usagestd::cout << *spt << "\n";}else {std::cout << "gw is expired\n";}
}int test_weak_ptr1()
{{auto sp = std::make_shared<int>(42);gw = sp;f();}f();return 0;
}/
// reference: http://stackoverflow.com/questions/12030650/when-is-stdweak-ptr-useful
int test_weak_ptr2()
{// OLD, problem with dangling pointer// PROBLEM: ref will point to undefined data!int* ptr = new int(10);int* ref = ptr;delete ptr;// NEW// SOLUTION: check expired() or lock() to determine if pointer is valid// empty definitionstd::shared_ptr<int> sptr;// takes ownership of pointersptr.reset(new int);*sptr = 10;// get pointer to data without taking ownershipstd::weak_ptr<int> weak1 = sptr;// deletes managed object, acquires new pointersptr.reset(new int);*sptr = 5;// get pointer to new data without taking ownershipstd::weak_ptr<int> weak2 = sptr;// weak1 is expired!if (auto tmp = weak1.lock())std::cout << *tmp << '\n';elsestd::cout << "weak1 is expired\n";// weak2 points to new data (5)if (auto tmp = weak2.lock())std::cout << *tmp << '\n';elsestd::cout << "weak2 is expired\n";return 0;
}//
// reference: https://msdn.microsoft.com/en-us/library/hh279672.aspx
class Controller
{
public:int Num;std::string Status;std::vector<std::weak_ptr<Controller>> others;explicit Controller(int i) : Num(i), Status("On"){std::cout << "Creating Controller" << Num << std::endl;}~Controller(){std::cout << "Destroying Controller" << Num << std::endl;}// Demonstrates how to test whether the pointed-to memory still exists or not.void CheckStatuses() const{for_each(others.begin(), others.end(), [](std::weak_ptr<Controller> wp) {try {auto p = wp.lock();std::cout << "Status of " << p->Num << " = " << p->Status << std::endl;}catch (std::bad_weak_ptr b) {std::cout << "Null object" << std::endl;}});}
};void RunTest()
{std::vector<std::shared_ptr<Controller>> v;v.push_back(std::shared_ptr<Controller>(new Controller(0)));v.push_back(std::shared_ptr<Controller>(new Controller(1)));v.push_back(std::shared_ptr<Controller>(new Controller(2)));v.push_back(std::shared_ptr<Controller>(new Controller(3)));v.push_back(std::shared_ptr<Controller>(new Controller(4)));// Each controller depends on all others not being deleted.// Give each controller a pointer to all the others. for (int i = 0; i < v.size(); ++i) {for_each(v.begin(), v.end(), [v, i](std::shared_ptr<Controller> p) {if (p->Num != i) {v[i]->others.push_back(std::weak_ptr<Controller>(p));std::cout << "push_back to v[" << i << "]: " << p->Num << std::endl;}});}for_each(v.begin(), v.end(), [](std::shared_ptr<Controller>& p) {std::cout << "use_count = " << p.use_count() << std::endl;p->CheckStatuses();});
}int test_weak_ptr3()
{RunTest();std::cout << "Press any key" << std::endl;char ch;std::cin.getline(&ch, 1);return 0;
}// reference: https://oopscenities.net/2014/08/03/c-smart-pointers-part-5-weak_ptr/
struct Child;
struct Parent
{std::shared_ptr<Child> child;~Parent() { std::cout << "Bye Parent" << std::endl; }void hi() const { std::cout << "Hello" << std::endl; }
};struct Child
{std::weak_ptr<Parent> parent;//std::shared_ptr<Parent> parent; // memory leak~Child() { std::cout << "Bye Child" << std::endl; }
};int test_weak_ptr4()
{auto parent = std::make_shared<Parent>();auto child = std::make_shared<Child>();parent->child = child;child->parent = parent;child->parent.lock()->hi();// child->parent->hi();return 0;
}/
// reference: http://thispointer.com/shared_ptr-binary-trees-and-the-problem-of-cyclic-references/
class Node
{int value;
public:std::shared_ptr<Node> leftPtr;std::shared_ptr<Node> rightPtr;// Just Changed the shared_ptr to weak_ptrstd::weak_ptr<Node> parentPtr;Node(int val) : value(val) {std::cout << "Contructor" << std::endl;}~Node() {std::cout << "Destructor" << std::endl;}
};int test_weak_ptr5()
{std::shared_ptr<Node> ptr = std::make_shared<Node>(4);ptr->leftPtr = std::make_shared<Node>(2);ptr->leftPtr->parentPtr = ptr;ptr->rightPtr = std::make_shared<Node>(5);ptr->rightPtr->parentPtr = ptr;std::cout << "ptr reference count = " << ptr.use_count() << std::endl;std::cout << "ptr->leftPtr reference count = " << ptr->leftPtr.use_count() << std::endl;std::cout << "ptr->rightPtr reference count = " << ptr->rightPtr.use_count() << std::endl;std::cout << "ptr->rightPtr->parentPtr reference count = " << ptr->rightPtr->parentPtr.lock().use_count() << std::endl;std::cout << "ptr->leftPtr->parentPtr reference count = " << ptr->leftPtr->parentPtr.lock().use_count() << std::endl;return 0;
}
GitHub:https://github.com/fengbingchun/Messy_Test
相关文章:

经典不过时,回顾DeepCompression神经网络压缩
作者 | 薰风初入弦转载自知乎导读:本文作者为我们详细讲述了 ICLR 2016 的最佳论文 Deep Compression 中介绍的神经网络压缩方法。神经网络压缩一直是一个重要的研究方向,而目前业界最认可的压缩方法莫过于 ICLR 2016 的最佳论文 Deep Compression&#…

区块链技术特点之去中心化特性
想知道更多关于区块链技术知识,请百度【链客区块链技术问答社区】 链客,有问必答!! 由于区块链技术去中心化的特性,其在我们生活中的很多重要领域(如金融、管理)等方面具有重要的意义。例如&…

Android APK反编译
转自:http://blog.csdn.net/ithomer/article/details/6727581 一、Apk反编译得到Java源代码 下载上述反编译工具包,打开apk2java目录下的dex2jar-0.0.9.9文件夹,内含apk反编译成java源码工具,以及源码查看工具。 apk反编译工具dex…
Java泛型进阶 - 如何取出泛型类型参数
在JDK5引入了泛型特性之后,她迅速地成为Java编程中不可或缺的元素。然而,就跟泛型乍一看似乎非常容易一样,许多开发者也非常容易就迷失在这项特性里。多数Java开发者都会注意到Java编译器的类型擦除实现方式,Type Erasure会导致关…

C++11中override的使用
override是C11中的一个继承控制关键字。override确保在派生类中声明的重载函数跟基类的虚函数有相同的声明。 override明确地表示一个函数是对基类中一个虚函数的重载。更重要的是,它会检查基类虚函数和派生类中重载函数的签名不匹配问题。如果签名不匹配ÿ…

平头哥发布一站式芯片设计平台“无剑”,芯片设计成本降低50%
导读:8 月 29 日,在上海举行的世界人工智能大会上,阿里巴巴旗下半导体公司平头哥发布 SoC 芯片平台“无剑”。无剑是面向 AIoT 时代的一站式芯片设计平台,提供集芯片架构、基础软件、算法与开发工具于一体的整体解决方案ÿ…

Windows XP下,JDK环境变量配置
2019独角兽企业重金招聘Python工程师标准>>> 1.安装JDK,安装过程中可以自定义安装目录等信息,例如我们选择安装目录为D:\java\jdk1.5.0_08; 2.安装完成后,右击“我的电脑”,点击“属性”; 3.选择…

Markdown语法简介
Markdown是一种方便记忆、书写的纯文本标记语言,用户可以使用这些标记符号以最小的输入代价生成极富表现力的文档。它目标是实现易读易写。Markdown的语法全由一些符号所组成。Markdown语法的目标是成为一种适用于网络的书写语言。 Markdown优点:纯文本…

吴恩达:AI未来将呈现四大发展趋势
作者 | 夕颜出品 | AI科技大本营(ID:rgznai100)导读:8 月 30 日,世界人工智能大会精彩继续。在今天的全球工业智能峰会上,Landing.AI 创始人及首席执行官吴恩达来到现场,做了题为《人工智能是新电力》的演讲…

嵌入式课程安排 嵌入式培训课程大纲参考
嵌入式是一门综合性的学科,现在学习嵌入式开发不是单纯局限于单片机或者Linux,嵌入式课程中包含着非常多的内容。以粤嵌嵌入式课程进行参考,看看我们要学习嵌入式的话,要掌握哪些必备的技能。嵌入式课程安排包含:1、入…

Linux网站架构系列之Apache----进阶篇
本篇博文为Linux网站架构系列之apache的第二篇,我将带大家一起学习apache的编译参数,目录结构和配置文件等方面的知识,实现对apache服务的进一步掌握,并使之能更好的应用到生产实战中去。一、编译参数在上篇的apache部署中&#x…

仅用10天设计的JavaScript,凭什么成为程序员最受欢迎的编程语言?
导语:在这个世纪之交诞生的 JavaScript,没人想到会发展为当今世界上最流行的语言之一。它不够成熟,不够严肃,甚至连名字都是模仿的 Java。那么,JavaScript 的成功是依靠运气和完美时机的侥幸吗?其实不然——…

C++11中= delete;的使用
C11中,对于deleted函数,编译器会对其禁用,从而避免某些非法的函数调用或者类型转换,从而提高代码的安全性。 对于 C 的类,如果程序员没有为其定义特殊成员函数,那么在需要用到某个特殊成员函数的时候&…

vue 使用scss
使用vue-cli模板创建的项目中,使用scss步骤 1. cmd命令: cnpm install sass-loader --save-devcnpm install node-sass --sava-dev2.查看package.json文件中是否已自动添加以下信息 3. 转载于:https://www.cnblogs.com/duanzhenzhen/p/10453495.html

EBS form日历可选范围设置(calendar.setup )介绍
Calendar是Template提供给我们的standard object.可以使我们方便的为日期型字段提供日期的选择列表.form中设置日历方法:1. 为日期型字段指定LOV(ENABLE_LIST_LAMP)2. 在字段的KEY–LISTVAL事件中编写代码:Calendar.showCalendar Package包含如下几个Procedure:1. Calendar.sho…

人工智能对地球环境科学的推进
一项德国耶拿[1]和汉堡[2]科学家在《自然》杂志发起的研究表明,人工智能可以有效地推进我们对于地球气候系统的理解。特别是在当前深度学习的潜力还未被完全开发的情况下。在人工智能的帮助下一些复杂的动态环境,如飓风,森林火灾,…

从概念到应用,终于有人把数据挖掘讲明白了
作者:陈封能(Pang-Ning Tan)、迈克尔斯坦巴赫(Michael Steinbach)等来源 | 大数据(ID: hzdashuju)【导语】数据采集和存储技术的迅速发展,加之数据生成与传播的便捷性&am…

C++11中default的使用
在C11中,对于defaulted函数,编译器会为其自动生成默认的函数定义体,从而获得更高的代码执行效率,也可免除程序员手动定义该函数的工作量。 C的类有四类特殊成员函数,它们分别是:默认构造函数、析构函数、拷…

Android开发:setAlpha()方法和常用RGB颜色表----颜色, r g b分量数值(int), 16进制表示 一一对应...
杂家前文Android颜色对照表只有颜色和十六进制,有时候需要设置r g b分量的int值,如paint.setARGB(255, 127, 255, 212);就需要自己计算下分量的各个值。这里提供一个带有r g b分量的int型的颜色表。注意paint.setAlpha()及paint.setARGB(&…

【redis】c/c++操作redis(对于hiredis的封装)
前言 最近一直在学习redis,通过c/cpp来执行redis命令,使用的是hiredis客户端来实现的。 先简单贴一下代码 头文件 #include <vector> #include <string> #include <hiredis/hiredis.h> typedef enum en_redisResultType {redis_reply_…
OpenCV代码提取:transpose函数的实现
OpenCV中的transpose函数实现图像转置,公式为:目前fbc_cv库中也实现了transpose函数,支持多通道,uchar和float两种数据类型,经测试,与OpenCV3.1结果完全一致。实现代码transpose.hpp:// fbc_cv …

只给测试集不给训练集,要怎么做自己的物体检测器?
9 月5 日,下周四,大家期待已久的由《动手学深度学习》作者,亚马逊首席科学家亲自带领的「深度学习实训营」就要在北京开营了。今天,李沐已经把这次深度学习实训营白天的教学内容和代码上传到 Gituhub 和 D2L.ai 网站了,…

MYSQL忘记登录密码
1、关闭Mysql: 如果 MySQL 正在运行,首先杀之 killall -TERM mysqld 2、另外的方法启动 MySQL :bin/safe_mysqld --skip-grant-tables 3、可以不需要密码就进入 MySQL 了。 然后就是 >use mysql>update user set passwordpassword(&qu…
OpenCV代码提取:flip函数的实现
OpenCV中实现图像翻转的函数flip,公式为:目前fbc_cv库中也实现了flip函数,支持多通道,uchar和float两种数据类型,经测试,与OpenCV3.1结果完全一致。实现代码flip.hpp:// fbc_cv is free softwar…

NLP这两年:15个预训练模型对比分析与剖析
作者 | JayLou来源 | 知乎前言在之前写过的《NLP的游戏规则从此改写?从word2vec, ELMo到BERT》一文中,介绍了从word2vec到ELMo再到BERT的发展路径。而在BERT出现之后的这大半年的时间里,模型预训练的方法又被Google、Facebook、微软、百度、O…

大三下学期第一周总结
本周以是开学第一周了,在生活方面,生活琐事确实变多了起来。每天上课,看着老师熟悉的面庞,如履春风。感觉学习没有那么多的陌生恐惧。学习是一方面,身体锻炼不能落下。一周至少保证三小时及其以上的运动。身体是革命的…

AD rodc扩展报错
AD rodc扩展报错AD RODC抢夺FSMO五大角色后,架构扩展报错,解决办法参考链接:http://support.microsoft.com/kb/949257/en-us

Dropout、梯度消失/爆炸、Adam优化算法,神经网络优化算法看这一篇就够了
作者 | mantch来源 | 知乎1. 训练误差和泛化误差对于机器学习模型在训练数据集和测试数据集上的表现。如果你改变过实验中的模型结构或者超参数,你也许发现了:当模型在训练数据集上更准确时,它在测试数据集上却不⼀定更准确。这是为什么呢&am…

入行AI,你需要一本Python机器学习入门
目前机器学习红遍全球。男女老少都在学机器学习模型,分类器,神经网络和吴恩达。你也想成为一份子,但你该如何开始?今天小编推荐这本《Python机器学习》教你快速入门。01什么是机器学习?从出生的那天起,…
通过transpose和flip实现图像旋转90/180/270度
在fbc_cv库中,提供了对图像进行任意角度旋转的函数rotate,其实内部也是调用了仿射变换函数warpAffine。如果图像仅是进行90度倍数的旋转,是没有必要用warpAffine函数的。这里通过transpose和flip函数实现对图像进行顺时针90度、180度、270度的…