unique_ptr指针详解:unique_ptr指针详解

shared_ptr指针详解:shared_ptr指针详解

weak_ptr指针详解:weak_ptr指针详解

shared_ptr中的owner_before解析

shared_ptr中的owner_before成员函数

shared_ptr中的owner_before成员函数的功能为“判断两个指针是否指向同一对象”。

shared_ptr中的owner_pointer和stored_pointer

shared_ptr指针其实根据属性不同可分为两种:

① owner pointer所有权拥有指针:

所有权拥有指针顾名思义就是指“这个指针指向整个自定义数据类型的对象而非该对象的成员数据”。

② stored pointer指向存储在内部的数据的指针:

stored pointer看名称也可以很清晰的理解:这个指针指向自定义数据类型对象的一部分。

两者的关系如下图所示:

什么是“C++中的弱序”?

① ptr和ptr1是不是同类型指针;

② ptr指针指向的地址小于ptr1指针指向的地址;

满足以上两种条件,我们就可以称“ptr<ptr1”。我们很可能想到“求同存异”,这四个字很符合“C++中弱序”的特点,因此我们要理解弱序就必须要理解“弱序到底求得什么同存的什么异”!

但是,我们的疑惑又来了:ptr与ptr1满足什么条件才可以被称之为“同类型指针”呢?

首先,我们知道shared_ptr有两种属性,因此ptr与ptr1的搭配方式有四种:

ptr指针属性

ptr1指针属性

stored_pointer

owner_pointer

owner_pointer

stored_pointer

owner_pointer

owner_pointer

stored_pointer

stored_pointer

每种搭配方式举例说明:

⑴ ptr1是stored_pointer而ptr是owner_pointer

代码示例:

#include <iostream>
using namespace std;
#include <memory>  struct A
{  int age;  double mark;
};  int main()
{  shared_ptr<A> ptr = make_shared<A>();  shared_ptr<int> ptr1(ptr, &ptr->age);  cout << "ptr指针指向的地址为" << ptr.get() << endl;  cout << "ptr1指针指向的地址为" << ptr1.get() << endl;  cout << "ptr1.owner_before(ptr) = " << ptr1.owner_before(ptr) << endl;  cout << "ptr.owner_before(ptr1) = " << ptr.owner_before(ptr1) << endl;
}  

运行结果:

在程序中我们看到:

指针名称

指针指向的目标

ptr

A类类型对象

ptr1

A类类型对象中的age成员数据

“弱序”中,将指向同一对象的shared_ptr指针作为同一类型的指针:

此时,向上面所示的stored_pointer和owner_pointer两个指针在“弱序”中属于同一类型的指针。

由于ptr和ptr1是同类型指针而且ptr指针等于ptr1指针指向地址,因此:

无论参数顺序如何,都不会影响最终的结果。

⑵ ptr和ptr1指针均为stored_pointer属性的shared_ptr指针

代码示例:

#include <iostream>
using namespace std;
#include <memory>  struct A
{  int age;  double mark;
};  int main()
{  shared_ptr<A> ptr = make_shared<A>();  shared_ptr<int> ptr1(ptr, &ptr->age);  shared_ptr<double> ptr2(ptr, &ptr->mark);  cout << "ptr1指向的地址为" << ptr1.get() << endl;  cout << "ptr2指向的地址为" << ptr2.get() << endl;  cout << "ptr1.owner_before(ptr2) = " << ptr1.owner_before(ptr2) << endl;  cout << "ptr2.owner_before(ptr1) = " << ptr2.owner_before(ptr1) << endl;
}  

运行结果:

我们看到ptr1与ptr2指向的地址此时不一样了,但是无论参数位置如何,owner_before成员函数返回值仍为0,这说明“指向同一个自定义类类型对象中不同数据成员的两个stored_pointer属性的shared_ptr指针在‘弱序’中属于同一类型的指针”。ptr与ptr1关系如下所示:

⑶ ptr与ptr1均属于owner_pointer属性的shared_ptr指针

代码示例:

#include <iostream>
using namespace std;
#include <memory>  struct A
{  int ageA;  double markA;
};  struct B
{  int ageB;  double markB;
};  struct AB : public A, public B
{  };  int main()
{  shared_ptr<A> ptr = make_shared<A>();  shared_ptr<B> ptr1 = make_shared<B>();  shared_ptr<AB> ptr2 = make_shared<AB>();  cout << "ptr指向的地址为" << ptr.get() << endl;  cout << "ptr1指向的地址为" << ptr1.get() << endl;  cout << "ptr2指向的地址为" << ptr2.get() << endl;  cout << "ptr(指向class A的对象)与ptr1(指向class B的对象)" << endl;  cout << "ptr > ptr1 = " << ((int)ptr.get() > (int)ptr1.get()) << endl;  cout << "ptr < ptr1 = " << ((int)ptr.get() < (int)ptr1.get()) << endl;  cout << "ptr.owner_before(ptr1)" << ptr.owner_before(ptr1) << endl;  cout << "ptr1.owner_before(ptr)" << ptr1.owner_before(ptr) << endl;  cout << "ptr(指向class A的对象)与ptr2(指向class AB的对象)" << endl;  cout << "ptr > ptr2 = " << ((int)ptr.get() > (int)ptr2.get()) << endl;  cout << "ptr < ptr2 = " << ((int)ptr.get() < (int)ptr2.get()) << endl;  cout << "ptr.owner_before(ptr2)" << ptr.owner_before(ptr2) << endl;  cout << "ptr2.owner_before(ptr)" << ptr2.owner_before(ptr) << endl;  cout << "ptr1(指向class B的对象)与ptr2(指向class AB的对象)" << endl;  cout << "ptr1 > ptr2 = " << ((int)ptr1.get() > (int)ptr2.get()) << endl;  cout << "ptr1 < ptr2 = " << ((int)ptr1.get() < (int)ptr2.get()) << endl;  cout << "ptr1.owner_before(ptr2)" << ptr1.owner_before(ptr2) << endl;  cout << "ptr2.owner_before(ptr1)" << ptr2.owner_before(ptr1) << endl;
}  

运行结果:

ptr,ptr1与ptr2的指针指向如下:

我们看上述的继承关系也可以看出“同类型”的指针对如下:

指针名称

指针名称

ptr

ptr2

ptr1

ptr2

我们看到上述的“同类型指针对”其实都是“含有继承关系的”,因此在两个owner_pointer属性的shared_ptr指针有继承关系且我们用指向派生类对象的指针初始化指向基类对象的指针时,这两个指针属于“弱序中的同类型指针”。

最终,我们在分析结果时就可以看出“当ptr与ptr2指向的类类型对象含有继承关系时,ptr.owner_before(ptr2)||ptr2.owner_before(ptr) == 0“,即ptr与ptr2这两个指针在”弱序排列规则中“属于同等地位的指针,也就是我们常说的”==”只不过此时的”等于“是针对于弱序规则中的ptr和ptr2两个指针。

对owner_before成员函数进行总结

我们使用“shared_ptr/weak_ptr中的owner_before成员函数“去判断两个指针是否指向”同一对象“并不想知道”两个指针指向地址的先后顺序“,因此我们可以这样做”先使用C++逻辑运算中的逻辑或操作(||),然后再总体上取个非(!)操作“:

#include <iostream>
using namespace std;
#include <memory>  struct A
{  int age;  double mark;
};  int main()
{  shared_ptr<A> ptr = make_shared<A>();  shared_ptr<int> ptr1(ptr, &ptr->age);  cout << "ptr与ptr1指针是否指向同一对象:" << !(ptr.owner_before(ptr1) || ptr1.owner_before(ptr)) << endl;
}  

为什么使用逻辑或(||)操作?

因为ptr.owner_before(ptr1)返回true必须满足两个条件:

① ptr和ptr1两个指针指向的对象属于“同一类型的对象“;

② ptr指向的地址必须小于ptr1指向的地址;

当我们将ptr.owner_before(ptr1)的返回结果与ptr1.owner_before(ptr)的返回结果进行逻辑或(||)操作后,(ptr.owner_before(ptr1)||ptr1.owner_before(ptr))这个整体返回的值就排除了“ptr与ptr1两个指针指向地址先后“的干扰,因此如果” (ptr.owner_before(ptr1)||ptr1.owner_before(ptr)) “返回0就代表ptr与ptr1指针指向同一个类型的对象。

但是这样的看有些不爽,我们想要“当“ptr与ptr1指针指向同一个类型的对象”时,返回true,你却此时给我返回false,那么我就取个反就OK了,因此最终用于判断两个指针是否指向同一个类型对象的代码为“!(ptr.owner_before(ptr1)||ptr1.owner_before(ptr))”。

为什么不用>,<逻辑比较符号来进行“弱序中的比较操作”?

① 因为在shared_ptr模板类中重载>,<等逻辑符号两边的操作对象的数据类型必须相同,例如:

在上述例子中,ptr指向class A的对象,ptr1指向class AB的对象,此时如果我们使用逻辑运算符来进行比较,一看操作符两端操作对象类型就不可以,一边为class A类型一边为class AB类型,纵使class A与class AB两个类之间有继承关系,重载的逻辑运算符也不会比较出来什么结果,即没用。

代码示例:

#include <iostream>
using namespace std;
#include <memory>  struct A
{  int age;  int mark;
};  int main()
{  shared_ptr<A> ptr = make_shared<A>();  shared_ptr<int> ptr1(ptr, &ptr->age);  cout << (ptr1 > ptr) << endl; // 因为>逻辑操作符两端操作对象类型不同,因此该行出错
}  

运行结果:

② 不会进行“弱序规则下的大小比较”,只根据指针所指向的地址去判断指针的大小顺序

代码示例:

#include <iostream>
using namespace std;
#include <memory>  struct A
{  int age;  int mark;
};  int main()
{  shared_ptr<A> ptr = make_shared<A>();  shared_ptr<int> ptr1(ptr, &ptr->age), ptr2(ptr, &ptr->mark), ptr3(nullptr);  cout << (ptr1 < ptr2) << endl; // 由于ptr1,ptr2指向同一对象,无论如何比较弱序在弱序规则下,ptr1应该与ptr2属于同一类型  cout << (ptr1 > ptr2) << endl;
}  

运行结果:

显然逻辑运算符执行的功能不是“弱序下的指针比较大小”。如果遵从弱序下的排序规则,无论使用>还是<号进行比较,最终的逻辑结果都应该是0,即在弱序下ptr与ptr1两个指针处于同等地位。

shared_ptr中的owner_before解析(最易懂,最全面)相关推荐

  1. ISO7816协议深度解析-简单易懂协议详解(一)-- 复位,字符帧,及ATR

    1. 摘要 IC卡必须支持T=0或T=1的协议,但不是同时支持这两种协议,而终端则必须同时支持T=0和T=1的协议. • T=0通讯协议是异步半双工字符传输协议: • T=1通讯协议是异步半双工块传输 ...

  2. 10JavaScript中的预解析

    技术交流QQ群:1027579432,欢迎你的加入! 1.预解析 JavaScript代码是由浏览器中的JavaScript解析器来执行的.JavaScript解析器在运行JavaScript代码的时 ...

  3. Caffe中的损失函数解析

    Caffe中的损失函数解析 导言 在有监督的机器学习中,需要有标签数据,与此同时,也需要有对应的损失函数(Loss Function). 在Caffe中,目前已经实现了一些损失函数,包括最常见的L2损 ...

  4. 2020美国计算机研究生学校排名,2020 US.news 美国研究生院排名出炉,美中国际独家解析!...

    原标题:2020 US.news 美国研究生院排名出炉,美中国际独家解析! 今天,美国US.news发布了2020年美国研究生院排名.和往年一样,本次研究生院细分为商科.法学.教育.工程.医学(分为研 ...

  5. Exchange 2007 中特殊应用解析

    Exchange 2007 中特殊应用解析 标签:Exchange 原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 .作者信息和本声明.否则将追究法律责任.http://zhengwe ...

  6. python画图如何调整图例位置_matplotlib中legend位置调整解析

    在画一些曲线图(linecharts)时,常常会出现多条曲线同时画在一张图上面,这时候就需要对不同的曲线进行不同的标注,以使读者能够清晰地知道每条曲线代表的含义.当你画很少的几条曲线时,这时画图命令中 ...

  7. Django中的反向解析

    前提: url(r'^app/', include('app.urls',namespace='app')),url('^relation',views.relation,name='relation ...

  8. 加载vue文件步骤_vue中.vue文件解析步骤详解

    这次给大家带来vue中.vue文件解析步骤详解,vue中.vue文件解析的注意事项有哪些,下面就是实战案例,一起来看一下. 我们平时写的 .vue 文件称为 SFC(Single File Compo ...

  9. JavaScript中的预解析(变量提升)介绍!

    今天小千为大家介绍一下JavaScript中的预解析(变量提升).从什么是预解析及变量的预解析和函数的预解析及加载流程进行学习(注意:我们这里说的ES5中的预解析). 什么是解析 首先代码执行肯定需要 ...

  10. boost::spirit模块从不同序列中元素的解析输入填充单个融合序列

    boost::spirit模块从不同序列中元素的解析输入填充单个融合序列 实现功能 C++实现代码 实现功能 boost::spirit模块从不同序列中元素的解析输入填充单个融合序列 C++实现代码 ...

最新文章

  1. Thread start()方法和run()方法的区别
  2. python互斥锁_Python多线程如何使用互斥锁
  3. mysql----Linux下安装
  4. php过滤两个坐标,php判断两个坐标的方位角
  5. VC2019无法打开文件msvcrtd.lib和Spectre 缓解库相关问题
  6. 数据结构---二叉搜索树
  7. packt_Packt发行的$ 5 Java编程书籍:精通Java 9,Java 9高性能
  8. android获取app用户数据,专项研究:Android收集用户数据是iPhone的20倍!
  9. openim php sdk,imsdk_restapi-php-sdk
  10. 树形dp 没有上司的舞会
  11. python描述_Python描述符(Descriptor)入门
  12. audio-音频标签
  13. java实现头脑王者辅助答题_头脑王者2答题神器app-头脑王者2答题辅助神器安卓版v1.0...
  14. lan和adsl是什么信号_光纤、以太网、ADSL上网有什么区别?
  15. Unity3D ParticleSystem粒子系统
  16. c语言股价连续上涨的天数,为什么通达信没有连涨天数,我的通达信怎么没有连涨天数显示...
  17. 全球智能网联汽车出货量预计
  18. 网络速度单位及其读法----1Mbps的专业读法和1Mb/s的专业读法
  19. 找到能立刻开始的下一步行动 |进击
  20. python例子高考志愿填报系统入口_2019年四川高考志愿填报系统入口网址登录入口(最新)...

热门文章

  1. linux 中more、less 和 most 的区别
  2. 关于网站嵌入faceboook以及youtube视频
  3. MySQL said: Authentication plugin ‘caching_sha2_password‘ cannot be loaded... 阿星小栈
  4. 【离散数学III】命题逻辑——命题符号及联结词
  5. android自动播放音乐代码,Android MediaPlayer实现音乐播放器实例代码
  6. android SDL系列讲解(十三) 播放音乐库 SDL_mixer教程
  7. 计算机不支持win10 1809更新,Win10 1809更新失败解决方法
  8. SUPPA2 分析可变剪切(附详细代码)
  9. 31道Java核心面试题(不会的都看过来啦)
  10. 在 linux ubuntu 18.04 上运行QQ音乐