波奇学C++:智能指针(二):auto_ptr, unique_ptr, shared_ptr,weak_ptr

news2025/2/27 11:11:13

C++98到C++11:智能指针分为auto_ptr, unique_ptr, shared_ptr,weak_ptr,这几种智能都是为了解决指针拷贝构造和赋值的问题

auto_ptr:允许拷贝,但只保留一个指向空间的指针。

管理权转移,把拷贝对象的资源管理权转移给拷贝对象,导致被拷贝对象悬空,不能访问出问题 ap1置空

auto_ptr<Test> ap1(new Test());
auto_ptr<Test> ap3 = ap1;
// ap1=nullptr

如果不置空就会导致对象调用析构函数时,空间会被释放两次。但会导致ap1无法再使用。

模拟auto_ptr

template<class T>
class AutoPtr
{
public:
	AutoPtr(T* ptr)
		:_ptr(ptr)
	{}
	T& operator*()
	{
		return *_ptr;
	}
	T* operator->()
	{
		return _ptr;
	}
	~AutoPtr()
	{
		cout << "delete pointer" << _ptr << endl;
		delete _ptr;
	}
	AutoPtr(AutoPtr<T>& ap)
		:_ptr(ap._ptr)
	{
		ap._ptr = nullptr;
	}
private:
	T* _ptr;
};

 unique_ptr: 禁止拷贝

unique_ptr<A> up1(new A());
unique_ptr<A> up3=up1// 报错

模拟实现unique_ptr

template<class T>
class UniquePtr
{
public:
	UniquePtr(T* ptr)
		:_ptr(ptr)
	{}
	T& operator*()
	{
		return *_ptr;
	}
	T* operator->()
	{
		return _ptr;
	}
	~UniquePtr()
	{
		cout << "delete pointer" << _ptr << endl;
		delete _ptr;
	}
	UniquePtr(const UniquePtr<T>& up) = delete; // 禁止拷贝构造
	UniquePtr<T>& operator=(const UniquePtr<T>& up) = delete; //禁止默认生成赋值重载函数
private:
	
	T* _ptr;
};

shared_ptr:支持拷贝,无法解决循环引用

shared_ptr通过引用计数来防止被多次析构

引用计数

用一个变量来记录指向空间的指针数,当一个智能指针释放时,变量数值减一,当数值为0时才释放空间。

模拟share_ptr的实现

template<class T>
class SharedPtr
{
public:
	SharedPtr(T* ptr)
		:_ptr(ptr)
		,_pcount(new int(1))
	{}
	T& operator*()
	{
		return *_ptr;
	}
	T* operator->()
	{
		return _ptr;
	}
	~SharedPtr()
	{
		if (--(*_pcount) == 0)
		{
			
			cout << "delete pointer" << _ptr << endl;
			delete _ptr;
			delete _pcount;
		}
	}
	
private:

	T* _ptr;
	int* _pcount;
};

 shared_ptr的拷贝构造

SharedPtr(const SharedPtr<T>& sp)
		:_ptr(sp._ptr)
		,_pcount(sp._pcount)
	{
		(*_pcount)++;
	}
	

shared_ptr的赋值重载

SharedPtr<T>& operator=(const SharedPtr<T>& sp)
	{
		if (_ptr==sp._ptr)
		{
			return *this;
		}
		if (*_pcount == 1)
		{
			~SharedPtr();
		}
		else
		{
			(*_pcount)--;
			
		}
		*(sp._pcount)++;
		_pcount = sp._count;
		_ptr = sp._ptr;
		return *this;
	}

 循环引用问题

class Test
{
public:
	Test()
	{
		cout << "构造函数"<<" "<<this << endl;
	}
	Test* fun()
	{
		return this;
	}
	~Test()
	{
		cout << "析构" << endl;
	}

};
struct Node
{
	Test test;
	shared_ptr<Node> _next;
	shared_ptr<Node> _prev;
};
int main()
{
	shared_ptr<Node> sp1(new Node);
	shared_ptr<Node> sp2(new Node);
	sp1->_next = sp2;
    sp2->_prev=sp1
	return 0;
}

当sp1 和sp2析构时,引用计数减为1

当要释放左边空间->释放右边空间的_prev->释放左边的_next->释放左边的空间。

释放左边空间->释放左边空间

形成死循环无法解决。

weak_ptr:解决shared_ptr循环引用问题,不属于RAII智能指针

struct Node
{
	Test test;
	weak_ptr<Node> _next;
	weak_ptr<Node> _prev;
};

weak_ptr:解决原理不增加引用计数

template<class T>
class WeakPtr
{
public:
	WeakPtr()
		:_ptr(nullptr)
	{}
	WeakPtr(const SharedPtr<T>& sp)
		:_ptr(sp._ptr)
	{}
	WeakPtr<T>& operator= (SharedPtr<T>& sp)
	{
		_ptr = sp.get();
		return *this;

	}
	T& operator*()
	{
		return *_ptr;
	}
	T* operator->()
	{
		return _ptr;
	}
private:
	T* _ptr;
};

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1278429.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Centos7.9搭建zabbix6.4.0过程及报错注意点

搭建参考此链接即可&#xff1a;https://blog.csdn.net/PerDrix/article/details/129624091 报错整理&#xff1a; 一、zabbix6.0以上版本默认必须安装mysql 8.0.30以上版本数据库&#xff0c;否则服务起不来 二、编译安装zabbix时&#xff0c;必须执行如下操作&#xff0c;…

LeetCode算法题解(动态规划)|LeetCode1143. 最长公共子序列、LeetCode1035. 不相交的线、LeetCode53. 最大子数组和

一、LeetCode1143. 最长公共子序列 题目链接&#xff1a;1143. 最长公共子序列 题目描述&#xff1a; 给定两个字符串 text1 和 text2&#xff0c;返回这两个字符串的最长 公共子序列 的长度。如果不存在 公共子序列 &#xff0c;返回 0 。 一个字符串的 子序列 是指这样一…

四、设置主机名和域名映射

目录 1、配置每台虚拟机主机名 2、配置每台虚拟机域名映射 1、配置每台虚拟机主机名

Unity对接后台和加载图片

1、前言 在unity中与后台对接&#xff0c;用await在web端暂时还不支持&#xff0c;所以&#xff0c;协程成为比较好的通用方式&#xff0c;以下适用除post访问外的所有对接 2、对接后台 2.1、安装插件 首先我们需要用到Newtonsoft.dll&#xff0c;如果没有这个.dll的请跟着我…

vue权限管理解决方案

一. 什么是权限管理 权限控制是确保用户只能访问其被授权的资源和执行其被授权的操作的重要方面。而前端权限归根结底是请求的发起权&#xff0c;请求的发起可能有下面两种形式触发 页面加载触发页面上的按钮点击触发 总体而言&#xff0c;权限控制可以从前端路由和视图两个…

QProcess 启动 进程 传参数 启动控制台进程 传参

目录 QProcess 启动外部程序的两种方式 依赖式 分离式&#xff1a; 启动进程前的预处理 设置启动路径 设置启动命令参数 设置启动工作目录 设置启动所需环境&#xff1a; 启动的状态 code smple: QProcess 控制台进程 QProcess启动控制台不显示窗口 注意&#xff1a;…

jvm基本概念,运行的原理,架构图

文章目录 JVM(1) 基本概念:&#xff08;2&#xff09;运行过程 今天来和大家聊聊jvm&#xff0c; JVM (1) 基本概念: JVM 是可运行Java代码的假想计算机&#xff0c;包括一套字节码指令集、一组寄存器、一个栈一个垃圾回收&#xff0c;堆 和 一个存储方法域。JVM 是运行在操作…

9.ROS的TF坐标变换(三):坐标系关系查看与一个案例

1 查看目前的坐标系变化 我们先安装功能包&#xff1a; sudo apt install ros-melodic-tf2-tools安装成功&#xff01; 我们先启动上次的发布坐标变换的节点&#xff1a; liuhongweiliuhongwei-Legion-Y9000P-IRX8H:~/Desktop/final/my_catkin$ source devel/setup.bash liuho…

cyclictest 交叉编译与使用

目录 使用版本问题编译 numactl编译 cyclictest使用参考 cyclictest 主要是用于测试系统延时&#xff0c;进而判断系统的实时性 使用版本 rt-tests-2.6.tar.gz numactl v2.0.16 问题 编译时&#xff0c;需要先编译 numactl &#xff0c;不然会有以下报错&#xff1a; arm-…

Linux:优化原则

web系统的优化原则&#xff1a; 从单机到集群 对Linux系统自身的优化原则&#xff1a;

TCP报文解析

1.端口号 标记同一台计算机上的不同进程 源端口&#xff1a;占2个字节&#xff0c;源端口和IP的作用是标记报文的返回地址。 目的端口&#xff1a;占2个字节&#xff0c;指明接收方计算机上的应用程序接口。 TCP报头中的源端口号和目的端口号同IP报头中的源IP和目的IP唯一确定一…

【QT】Windows环境下,cmake引入QML

这里使用的QT库为5.7版本。 1、添加环境变量 QT库根目录环境变量 QTDIR QT库平台插件环境变量 QT_PLUGIN_PATH QML支持环境变量 QML2_IMPORT_PATH &#xff08;该环境变量仅在需要使用QML时添加&#xff09; QT库动态库环境变量&#xff0c;bin目录下包含了QT程序运行所需的dl…

电子学会C/C++编程等级考试2022年03月(四级)真题解析

C/C++等级考试(1~8级)全部真题・点这里 第1题:拦截导弹 某国为了防御敌国的导弹袭击, 发展出一种导弹拦截系统。 但是这种导弹拦截系统有一个缺陷: 虽然它的第一发炮弹能够到达任意的高度,但是以后每一发炮弹都不能高于前一发的高度。 某天, 雷达捕捉到敌国的导弹来袭。…

第十一届蓝桥杯青少组省赛Python中高级组真题及赏析

练习最好的办法就是实战。拿真题来做&#xff0c;不是解析是赏析。带着欣赏的眼光看&#xff0c;题目不但不难&#xff0c;反倒增加不少乐趣。接下来揭开第十一届蓝桥杯青少组省赛python编程题的神秘面纱&#xff0c;我们来一一赏析&#xff0c;看难不难。 选择题 选择题都比较…

C++核心编程——类与对象基础

C核心编程——类与对象基础 类与对象封装构造函数普通构造拷贝构造初始化成员列表&#xff08;补充&#xff09; 析构函数对象数组对象指针指向对象的指针指向对象成员的指针this指针 静态成员静态数据成员静态成员函数 友元普通函数做友元函数友元成员函数友元类 类与对象 C面…

深度学习常见回归分支算法逐步分析,各种回归之间的优缺点,适用场景,举例演示

文章目录 1、线性回归&#xff08;Linear Regression&#xff09;1.1 优点1.2 缺点1.3 适用场景1.4 图例说明 2、多项式回归&#xff08;Polynomial Regression&#xff09;2.1 优点2.2 缺点2.3 适用场景2.4 图例说明 3、决策树回归&#xff08;Decision Tree Regression&#…

Linux基础命令(超全面,建议收藏!)

一、Linux的目录结构 /&#xff0c;根目录是最顶级的目录了 Linux只有一个顶级目录&#xff1a;/ 路径描述的层次关系同样使用/来表示 /home/itheima/a.txt&#xff0c;表示根目录下的home文件夹内有itheima文件夹&#xff0c;内有a.txt 二、Linux命令基础格式 无论是什么…

孩子都能学会的FPGA:第十八课——用FPGA实现定点数的除法

&#xff08;原创声明&#xff1a;该文是作者的原创&#xff0c;面向对象是FPGA入门者&#xff0c;后续会有进阶的高级教程。宗旨是让每个想做FPGA的人轻松入门&#xff0c;作者不光让大家知其然&#xff0c;还要让大家知其所以然&#xff01;每个工程作者都搭建了全自动化的仿…

vivado实现分析与收敛技巧6-策略建议

典型时序收敛策略需运行大量实现策略并选取其中最佳的策略以供在实验室内应用。 ML 策略同样可选 &#xff0c; 且只需您运行3 项策略即可达成类似的 QoR 收益。这些策略使用机器学习来检验布线后设计的各项功能特性 &#xff0c; 以便预测相同设计上不同策略的性能。在 repo…

树莓派4b安装ubuntu22和向日葵设置开机启动

树莓派4b安装ubuntu22和向日葵设置开机启动 使用树莓派烧录系统工具烧录ubuntu 在树莓派官网下载官方软件&#xff0c;安装完后运行 在软件上选择 选择ubuntu桌面或者server 根据自己需求选择&#xff0c;这里我选择22.04的系统 烧录好以后进入系统 安装向日葵 下载树莓…