当前位置: 首页 > news >正文

【C++ techniques】Smart Pointers智能指针

Smart Pointers智能指针

看起来、用起来、感觉起来像内置指针,但提供更多的机能。拥有以下各种指针行为的控制权:

  1. 构造和析构;
  2. 复制和赋值;
  3. 解引。

Smart Pointers的构造、赋值、析构

C++的标准程序库提供的auto_ptr template:
auto_ptr对象是个smart pointer,用来指向诞生于堆内的对象,直到该auto_ptr被销毁为止;当销毁发生时,auto_ptr的析构函数会删除其所指物。

template<class T>
class auto_ptr
{
public:auto_ptr(T* ptr):pointee(ptr){}~auto_ptr(){delete pointee;}...
private:T* pointee;
};

在“同一对象只可被一个auto_ptr拥有”的前提下,上述做法可以有效运作;但当auto_ptr被复制或被赋值,其“对象拥有权”会转移:

template<class T>
class auto_ptr
{
public:...auto_ptr(auto_ptr<T>& rhs);auto_ptr<T>& operator = (auto_ptr<T>& rhs);...
};							template<class T>
auto_ptr<T>::auto_ptr(auto_ptr<T>& rhs)
{pointee = rhs.pointee;  //将*pointee的拥有权转移至*thisrhs.pointee = 0;		//rhs不再拥有任何东西
}template<class T>
auto_ptr<T>& auto_ptr<T>::operator = (auto_ptr<T>& rhs)
{if(this = &rhs)return *this;delete pointee; //必须删除目前拥有之物pointee = rhs.pointee;rhs.pointee = 0;return *this;
}

由于auto_ptr的复制构造函数被调用时,对象拥有权转移了,所以以by value方式传递auto_ptrs绝对不合适,Pass-by-refrence-to-const才是适当的途径。

void printTreeNode(ostream& s,auto_ptr<TreeNode> p)
{s << *p;
}int main()
{auto<TreeNode> ptn(new TreeNode);...printTreeNode(cout,ptn); //以by value方式传递auto_ptr
}//Pass-by-refrence-to-const方式
void printTreeNode(ostream& s, const auto_ptr<TreeNode>& p)
{s << *p;
}

实现Dereferencing Operators(解引操作符)

smart pointers的核心:operator*和operator->函数

//operator*
template<class T>
T& SmartPtr<T>::operator*() const
{///perform "smart pointer" processing;return *pointee;
}
//返回值是reference形式
//operator->
void editTuple(DBPtr<Tuple>& pt)
{LogEntry<Tuple> entry(*pt);do{pt->displayEditDialog();//会被编译器解释为(pt.operator->())->displayEditDialog();}while (pt->isValid == false)
}
//大部分时候想要operator->返回一个普通的dump pointer:
template<class T>
T* SmartPtr<T>::operator->() const
{//perform "smart pointer" processing;return pointee;
}

测试Smart Pointers是否为NULL

为smart pointer classes加上一个isNull函数很容易,但smart pointers 无法像dumb pointers那般自然地测试是否为null:

SmartPtr<TreeNode> ptn;
...
if(ptn == 0) ... //错误
if(ptn) ...		 //错误
if(!ptn) ...	 //错误

提供一个类型转换操作符,允许上述动作得以通过编译:

template<class T>
class SmartPtr
{
public:...operator void*(); //如果dumb ptr是null,返回零//否则返回非零值
};SmartPtr<TreeNode> ptn;
...
if(ptn == 0) ... //ok
if(ptn) ...		 //ok
if(!ptn) ...	 //ok

缺点:允许你把smart pointers拿来和完全不同的类型做比较:

SmartPtr<Apple> pa;
SmartPtr<Orange> po;
...
if(pa == po)  //竟然可以过关//重载“!操作符”
template<class T>
class SmartPtr
{
public:...bool operator!() const; //只有当smart ptr是null才返回true...
};//clients:
SmartPtr<TreeNode> ptn;
...
if(!ptn)
{...		
}else{...
}if(ptn == 0) ... 	//错误
if(ptn) ... 		//错误//唯一的风险:
SmartPtr<Apple> pa;
SmartPtr<Orange> po;
...
if(!pa == !po)	//竟然可通过编译

C++标准库中,“隐式转换为void*”已被“隐式转换为bool”取代,而operator bool总是返回operator!的反相。

将Smart Pointers转换为Dumb Pointers

如果为smart pointer-to-T template加上一个隐式类型转换函数,便可转换为dumb pointer-to-T:

Template<class T>
class DBPtr
{
public:...operator T*() const;  //新增的转换操作符...
};DBPtr<Tuple> pt;
...
normalize(pt);			//现在这就成功了//nullness测试问题也一并解决了:
if(ptn == 0) ... //可以
if(ptn) ...		 //可以
if(!ptn) ...	 //可以

与设计smart pointer目的相违背!也不要提供对dumb pointer的隐式转换操作符,除非不得已!

Smart Pointers和“和继承有关的”类型转换

我们真正想要知道的是如何能够将“smart pointers classes的行为”在“与继承相关类型转换”上,能够和dumb pointers一样。答案很简单:不能够。
smart pointers虽然smart,却不是pointers,我们所能做的最好情况就是使用member templates来产生转换函数,然后再在其中出现模棱两可的时候使用转型动作。

Smart Pointers 与 const

smart pointers中const只能施行于指针身上,不能用于其所指的对象;

类型转换如果涉及const,便是一条单行道:从non-const 转换成const是安全的,从const 转换成non-const则不安全。此外,能够对const做的任何事情,也都可以对non-const指针进行。

和public inheritance的规则类似,可以利用:
实现smart pointers时令一个smart pointer-to-T class公开继承一个对应的smart pointer-to-const-T class:

template<class T>
class SmartPtrToConst
{
public:... 					//一般都会有smart pointer member//functionsprotected:union{const T* constPointee;	 //给SmartPtrToConst使用T* pointee;				 //给SmartPtr使用};
};template<class T>
class SmartPtr:public SmartPtrToConst<T>
{...		  					//没有data members
}

相关文章:

【C++ techniques】Smart Pointers智能指针

Smart Pointers智能指针 看起来、用起来、感觉起来像内置指针&#xff0c;但提供更多的机能。拥有以下各种指针行为的控制权&#xff1a; 构造和析构&#xff1b;复制和赋值&#xff1b;解引。 Smart Pointers的构造、赋值、析构 C的标准程序库提供的auto_ptr template: au…...

LabVIEW利用以太网开发智能液位检测仪

LabVIEW利用以太网开发智能液位检测仪 目前&#xff0c;工业以太网接口在国内外的发展已经达到了相当深入的程度&#xff0c;特别是在自动化控制和工业控制领域有着非常广泛的应用。在工业生产过程中&#xff0c;钢厂的连铸机是前后的连接环节&#xff0c;其中钢水从大钢包进入…...

文字转语音:语音合成(Speech Synthesis) 数组文字循环播放

前言&#xff1a; HTML5中和Web Speech相关的API实际上有两类&#xff0c;一类是“语音识别(Speech Recognition)”&#xff0c;另外一个就是“语音合成(Speech Synthesis)”&#xff0c; 这两个名词实际上指的分别是“语音转文字”&#xff0c;和“文字变语音”。 speak() –…...

Spark基础

一、spark基础 1、为什么使用Spark Ⅰ、MapReduce编程模型的局限性 (1) 繁杂 只有Map和Reduce两个操作&#xff0c;复杂的逻辑需要大量的样板代码 (2) 处理效率低 Map中间结果写磁盘&#xff0c;Reduce写HDFS&#xff0c;多个Map通过HDFS交换数据 任务调度与启动开销大 (…...

localhost和127.0.0.1都可以访问项目,但是本地的外网IP不能访问

使用localhost和127.0.0.1都可以访问接口&#xff0c;比如&#xff1a; http://localhost:8080/zhgl/login/login-fy-list或者 http://127.0.0.1:8080/zhgl/login/login-fy-list返回json {"_code":10000,"_msg":"Success","_data":…...

快速掌握批量合并视频

在日常的工作和生活中&#xff0c;我们经常需要对视频进行编辑和处理&#xff0c;而合并视频、添加文案和音频是其中常见的操作。如何快速而简便地完成这些任务呢&#xff1f;今天我们介绍一款强大的视频编辑软件——“固乔智剪软件”&#xff0c;它可以帮助我们轻松实现批量合…...

OpenCV利用Camshift实现目标追踪

目录 原理 做法 代码实现 结果展示 原理 做法 代码实现 import numpy as np import cv2 as cv# 读取视频 cap cv.VideoCapture(video.mp4)# 检查视频是否成功打开 if not cap.isOpened():print("Error: Cannot open video file.")exit()# 获取第一帧图像&#x…...

使用pywin32读取doc文档的方法及run输出乱码 \r\x07

想写一个读取doc文档中表格数据&#xff0c;来对文档进行重命名。经查资料&#xff0c;py-docx无法读取doc文档&#xff0c;原因是这种是旧格式。所以&#xff0c;采用pywin32来进行读取。 import win32com.client as win32word win32.gencache.EnsureDispatch(Word.Applicati…...

一天一八股——TCP保活keepalive和HTTP的Keep-Alive

TCP属于传输层&#xff0c;关于TCP的设置在内核态完成 HTTP属于用户层的协议&#xff0c;主要用于web服务器和浏览器之间的 http的Keep-Alive都是为了减少多次建立tcp连接采用的保持长连接的机制&#xff0c;而tcp的keepalive是为了保证已经建立的tcp连接依旧可用(双端依旧可以…...

头部品牌停业整顿,鲜花电商的中场战事迎来拐点?

鲜花电商行业再次迎来标志性事件&#xff0c;曾经4年接连斩获6轮融资的明星品牌花加&#xff0c;正式宣布停业整顿。 梳理来看&#xff0c;2015年是鲜花电商赛道的发展爆发期&#xff0c;彼时花加等品牌相继成立&#xff0c;并掀起一波投资热潮&#xff0c;据媒体统计&#xf…...

深入解读redis的zset和跳表【源码分析】

1.基本指令 部分指令&#xff0c;涉及到第4章的api&#xff0c;没有具体看实现&#xff0c;但是逻辑应该差不多。 zadd <key><score1><value1><score2><value2>... 将一个或多个member元素及其score值加入到有序集key当中。根据zslInsert zran…...

elasticsearch内存占用详细分析

内存占用 ES的JVM heap按使用场景分为可GC部分和常驻部分。 可GC部分内存会随着GC操作而被回收&#xff1b; 常驻部分不会被GC&#xff0c;通常使用LRU策略来进行淘汰&#xff1b; 内存占用情况如下图&#xff1a; common space 包括了indexing buffer和其他ES运行需要的clas…...

【研究生学术英语读写教程翻译 中国科学院大学Unit3】

研究生学术英语读写教程翻译 中国科学院大学Unit1-Unit5 Unit3 Theorists,experimentalists and the bias in popular physics理论家,实验家和大众物理学的偏见由于csdn专栏机制修改,请想获取资料的同学移步b站工房,感谢大家支持!研究生学术英语读写教程翻译 中国科学院大学…...

基于虚拟同步发电机控制的双机并联Simulink仿真模型

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…...

微信小程序开发——自定义堆叠图

先看效果图 点击第一张图片实现折叠&#xff0c;再次点击实现展开 思路 图片容器绑定点击事件获取当前图片索引&#xff0c;触发onTap函数&#xff0c;根据索引判断当前点击的图片是否为第一张&#xff0c;并根据当前的折叠状态来更新每张图片的位置&#xff0c;注意图片向上…...

国庆day5

QT实现TCP服务器客户端搭建的代码 ser.h #ifndef SER_H #define SER_H#include <QWidget> #include<QTcpServer> #include<QTcpSocket> #include<QMessageBox> #include<QList> QT_BEGIN_NAMESPACE namespace Ui { class …...

经典算法----迷宫问题(找出所有路径)

目录 前言 问题描述 算法思路 定义方向 回溯算法 代码实现 前言 前面我发布了一篇关于迷宫问题的解决方法&#xff0c;是通过栈的方式来解决这个问题的&#xff08;链接&#xff1a;经典算法-----迷宫问题&#xff08;栈的应用&#xff09;-CSDN博客&#xff09;&#xff…...

macOS下 /etc/hosts 文件权限问题修复方案

文章目录 前言解决方案权限验证 macOS下 etc/hosts 文件权限问题修复 前言 当在 macOS 上使用 vi编辑 /etc/hosts 文件时发现出现 Permission Denied 的提示,就算在前面加上 sudo 也照样出现一样的提示,解决方案如下; 解决方案 可以尝试使用如下命令尝试解除锁定; sudo chf…...

【星海出品】ansible入门(二) playbook

核心是管理配置进行批量节点部署。 执行其中的一些列tasks。 playbook由YAML语言编写。 YAML的格式如下&#xff1a; 文件名应该以 .yml 结尾 1.文件的第一行应该以“—”&#xff08;三个连字符&#xff09;开始&#xff0c;表明YAML文件的开始。 2.在同一行中&#xff0c;#之…...

Spring Boot对账号密码进行加密储存

未来避免明文硬编码&#xff0c;我们需要对密码进行加密保存&#xff0c;例如账号密码 方法 在Spring Boot中&#xff0c;可以使用Jasypt&#xff08;Java Simplified Encryption&#xff09;库来对敏感信息进行加密和解密。Jasypt提供了一种简单的方式来在应用程序中使用加密…...

总结js中常见的层次选择器

js中的层次选择器可以用于选择和操作DOM树中的元素&#xff0c;根据元素的层级关系进行选择。以下是js中常见的层次选择器&#xff1a; 1. getElementById&#xff1a;使用元素的ID属性进行选择。通过给元素设置唯一的ID属性&#xff0c;可以使用getElementById方法选择该元素…...

阿里云ECS服务器上启动的portainer无法访问的问题

如下图&#xff0c;在阿里云ECS服务器上安装并启动了portainer&#xff0c;但是在自己电脑上访问不了远程的portainer。 最后发现是要在网络安全组里开放9000端口号&#xff0c;具体操作如下&#xff1a; 在云服务器管理控制台点击左侧菜单中的网络与安全-安全组&#xff0c;然…...

JavaScript系列从入门到精通系列第十八篇:JavaScript中的函数作用域

文章目录 前言 一&#xff1a;函数作用域 前言 我们刚才提到了&#xff0c;在<Script>标签当中进行定义的变量、对象、函数对象都属于全局作用域&#xff0c;全局作用域在页面打开的时候生效在页面关闭的时候失效。 一&#xff1a;函数作用域 调用函数时创建函数作用域…...

开环模块化多电平换流器仿真(MMC)N=6(Simulink仿真)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…...

[C]嵌入式中变量存储方案

#include<stdio.h>#define uint8_t unsigned char #define uint16_t unsigned short #define uint24_t unsigned int #define uint32_t unsigned int #define uint64_t unsigned long long//用户自定义变量名字&#xff0c;用于存储 typedef enum {first_run 0,//…...

热迁移中VirtIO-PCI设备的配置空间处理

文章目录 问题现象定位过程日志分析源端目的端 原理分析基本原理上下文分析复现分析patch分析 总结解决方案 问题现象 集群升级虚拟化组件版本&#xff0c;升级前存量运行并挂载了virtio磁盘的虚拟机集群内热迁移到升级后的节点失败&#xff0c;QEMU报错如下&#xff1a; 202…...

模拟滤波器的基础知识和设计

信号处理工作中滤波器的应用是非常广泛的&#xff0c;可以分成模拟滤波器和数字滤波器两种&#xff0c;数字滤波器主要包括两种&#xff0c;IIR和FIR&#xff0c;这两种滤波器后面统一说&#xff0c;今天先来说一说模拟滤波器&#xff08;主要是我先用Python实现了Matlab书里面…...

机器学习基础-Pandas学习笔记

Pandas Python的数据分析库&#xff0c;与Numpy配合使用&#xff0c;可以从常见的格式如CSV、JSON等中读取数据。可以进行数据清洗、数据加工工作。数据结构Series&#xff0c;Pandas.Series(data,index,dtype,name,copy) data类型是Numpy的ndarray类型&#xff0c;index指定下…...

【GIT版本控制】--协作流程

一、Fork与Pull Request Git协作流程中的关键概念包括Fork和Pull Request&#xff0c;它们允许多人在项目中协作并贡献代码。以下是关于Fork和Pull Request的简要总结&#xff1a; 1. Fork&#xff1a; Fork是指复制一个Git仓库&#xff0c;通常是一个开源项目的仓库&#xf…...

简析Cookie、Session、Token

手打不易&#xff0c;如果转摘&#xff0c;请注明出处&#xff01; 注明原文&#xff1a;https://zhangxiaofan.blog.csdn.net/article/details/133498756 文章目录 简析Cookie、Session、Token什么是 Cookie &#xff1f;什么是 Session &#xff1f;Cookie 和 Session 到底是…...

wordpress安装主题提示服务器错误/在线刷高质量外链

创建数据表 普通创建表&#xff1a;create table 表名(字段名 字段类型[字段属性],字段名 字段类型[字段属性],…)[表选项] create table mydatabase.class( -- mydatabase是已经存在的数据库name varchar(10))charset utf8;查询表 show tables; – 查看所有表 show tables l…...

网站平台建设所需开发工具/汕头网站推广

HBase的分页实现相对复杂一些。核心思想是结合分页过滤器PageFilter(pageSize)和查询设置开始行scan.setStartRow(lastRow)&#xff0c;lastRow为上一次查询rowkey&#xff0c;需要注意的是该rowkey是一个数组&#xff0c;对应多字段的存储位置;不同用户登录会产生不同lastRow&…...

泛微 企业网站建设计划/sns营销

欢迎喜欢实施运维及数据的小伙伴加入群进行谈论&#xff01; 运维技术群&#xff1a;263859509 lvs 原理 LVS通过工作于内核的ipvs模块来实现功能&#xff0c;其主要工作于netfilter 的INPUT链上。 而用户需要对ipvs进行操作配置则需要使用ipvsadm这个工具。 ipvsadm主要用于设…...

快速建设网站视频教程/网络营销的营销理念

JDK的动态代理机制只能代理实现了接口的类&#xff0c;而不能实现接口的类就不能实现JDK的动态代理&#xff0c;cglib是针对类来实现代理的&#xff0c;他的原理是对指定的目标类生成一个子类&#xff0c;并覆盖其中方法实现增强&#xff0c;但因为采用的是继承&#xff0c;所以…...

山东省旅游局网站建设情况/品牌营销策划书

Maven学习总结(五)——聚合与继承 一、聚合 如果我们想一次构建多个项目模块&#xff0c;那我们就需要对多个项目模块进行聚合 1.1、聚合配置代码 1 <modules> 2 <module>模块一</module> 3 <module>模块二</module> 4 <mo…...

精通网站建设pdf下载/什么是互联网营销师

转自&#xff1a;https://blog.csdn.net/yz9612/article/details/80234377 spring为hibernate的DAO提供工具类&#xff1a;HibernateDaoSupport。该类主要提供如下两个方法&#xff0c;方便DAO的实现&#xff1a; public final HibernateTemplate getHibernateTemplate() pu…...