智能指针解读(2)

news2024/10/3 0:24:01

前面一篇文章,我讲解了智能指针的原理,并实现了一个简单的智能指针。为了加深对智能指针的理解,在这篇文章中,我把C++中的几个智能指针讲解下:auto_ptr, unique_ptr, shared_ptr, weak_ptr。

1、auto_ptr

前面的文章我们把smart_ptr的拷贝构造函数、赋值运算符都禁掉了。auto_ptr在拷贝构造函数和赋值运算符里是怎么处理的呢?它会把原来的指针赋为nullptr。

template<class T>
class auto_ptr {
public:
	auto_ptr(T* _ptr) : ptr(_ptr) {

	}

	auto_ptr(auto_ptr& _ap) : ptr(_ap.ptr) {
		_ap.ptr = nullptr;
	}

	auto_ptr<T>& operator = (auto_ptr<T>& _ap) {
		if (ptr != _ap.ptr) {
			ptr = _ap.ptr;
			_ap.ptr = nullptr;
		}

		return *this;
	}

	~auto_ptr() {
		delete ptr;
		ptr = nullptr;
	}

	T& operator * () {
		return *ptr;
	}

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

3、unique_ptr

unique_ptr是c++11版本库中提供的智能指针,它直接将拷贝构造函数和赋值重载函数给禁用掉。所以unique_ptr只能move,不能赋值。

4、shared_ptr

shared_ptr允许多个智能指针可以指向同一块资源,并且能够保证共享的资源只会被释放一次。
shared_ptr采用的是引用计数原理来实现多个shared_ptr对象之间共享资源:
(1)引用计数用来记录该资源被几个对象共享。
(2)当一个shared_ptr对象被销毁时(调用析构函数),析构函数内就会将该计数减1。
(3)如果引用计数减为0后,则表示自己是最后一个使用该资源的shared_ptr对象,必须释放资源。
(4)如果引用计数不是0,就说明自己还有其他对象在使用,则不能释放该资源。

在使用shared_ptr时,要注意不要让2个shared_ptr指向同一个原始指针,比如:

A* p = new A(10);
shared_ptr<A> sp1(p), sp2(p);

sp1 和 sp2 并不会共享同一个对 p 的引用计数,而是各自将对 p 的引用计数都记为 1(sp2 无法知道 p 已经被 sp1 托管过)。这样,当 sp1 消亡时要析构 p,sp2 消亡时要再次析构 p,这会导致程序崩溃。

5、weak_ptr

weak_ptr类的对象可以指向shared_ptr,但不会改变shared_ptr的引用计数。一旦最后一个shared_ptr被销毁时,对象就会被释放。
weak_ptr并没有重载operator->和operator *操作符,因此不可直接通过weak_ptr使用对象,典型的用法是调用其lock函数来获得shared_ptr示例,进而访问原始对象。

我们来看一个shared_ptr交叉引用的例子:

class B;
class A
{
public:
	shared_ptr<B> sp;

	~A(){
		cout << "~A"<<endl;
	}
};
class B
{
public:
	shared_ptr<A> sp;
	~B(){
		cout << "~B"<<endl;
	}
};

void fun() {
	shared_ptr<B> pb(new B());
	shared_ptr<A> pa(new A());

	pb->sp = pa;
	cout << "pb.use_count " << pb.use_count() << endl;//1
	cout << "pa.use_count " << pa.use_count() << endl;//2

	pa->sp = pb;
	cout << "pb.use_count " << pb.use_count() << endl;//2
	cout << "pa.use_count " << pa.use_count() << endl;//2

    //并没有输出 ~A, ~B,也就是class B;
class A
{
public:
	shared_ptr<B> sp;

	~A(){
		cout << "~A"<<endl;
	}
};
class B
{
public:
	shared_ptr<A> sp;
	~B(){
		cout << "~B"<<endl;
	}
};

void fun() {
	shared_ptr<B> pb(new B());
	shared_ptr<A> pa(new A());

	pb->sp = pa;
	cout << "pb.use_count " << pb.use_count() << endl;//1
	cout << "pa.use_count " << pa.use_count() << endl;//2

	pa->sp = pb;
	cout << "pb.use_count " << pb.use_count() << endl;//2
	cout << "pa.use_count " << pa.use_count() << endl;//2

    //没有输出~A, ~B。也就是没有调用A和B的析构函数。
}

怎么去避免这种交叉引用呢?这就需要使用weak_ptr:把A中的shared_ptr<B> sp改为weak_ptr<B> sp_weak,这样传递时不会增加sp引用计数use_count()的值,所以最终能够使A、B资源正常释放:

class B;
class A
{
public:
	//shared_ptr<B> sp;
	weak_ptr<B> sp_weak;

	~A(){
		cout << "~A"<<endl;
	}
};
class B
{
public:
	shared_ptr<A> sp;
	~B(){
		cout << "~B"<<endl;
	}
};

void fun() {
	shared_ptr<B> pb(new B());
	shared_ptr<A> pa(new A());

	pb->sp = pa;
	cout << "pb.use_count " << pb.use_count() << endl;//1
	cout << "pa.use_count " << pa.use_count() << endl;//2

	//pa->sp = pb;
	pa->sp_weak = pb;
	cout << "pb.use_count " << pb.use_count() << endl;//1
	cout << "pa.use_count " << pa.use_count() << endl;//2

	shared_ptr<B> pa2 = pa->sp_weak.lock();

}

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

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

相关文章

在服务器上创建git仓库

1、在服务器上创建git仓库 选择一个创建文件夹的地方&#xff0c;这个地方不会将源码存放在这里&#xff0c;只用于版本控制 # 创建一个专门放置git的文件夹&#xff0c;也可以叫其它名 mkdir git && cd git # 创建自己项目的文件夹&#xff0c;文件夹后面要带 .git…

电工三级证(高级)实战项目:信号交通灯的PLC控制

实训目的 掌握比较指令掌握时钟指令掌握时间同步的方法 控制要求 PLC设备:Siemens S7-200 要求:按下起动按钮SB1后&#xff0c;东西方向绿灯亮20s&#xff0c;之后再闪烁绿灯3s&#xff0c;之后黄灯亮3s&#xff0c;最后红灯亮26s&#xff1b;同时&#xff0c;南北方向红灯亮…

Winscp--使用技巧

原文网址&#xff1a;Winscp--使用技巧_IT利刃出鞘的博客-CSDN博客 简介 本文介绍Winscp的使用技巧。 保持连接 有时经常自动断开&#xff0c;需要重新连接&#xff0c;解决方法如下&#xff1a; 修改默认目录 每次连接后会自动定位到如下目录&#xff1a;本地Windows的Do…

2023最新安装微信小程序开发软件安装教程

一&#xff0c;安装开发者工具 我们在开发小程序之前&#xff0c;首先需要安装小程序开发者工具&#xff0c;今天就来教大家安装小程序开发者工具。 微信开放文档 (qq.com)https://developers.weixin.qq.com/miniprogram/dev/framework/ 官网工具下载地址&#xff1a; 微信…

Linux 进程相关命令

输入 ps aux后里面有个STAT参数 kill -9 进程ID 或者kill -9 SIGKILL 进程ID强制杀死

76、SpringBoot 整合 MyBatis------使用 sqlSession 作为 Dao 组件(就是ssm那一套,在 xml 写sql)

就是 ssm 那套&#xff0c;在xml 上面写sql ★ 基于SqlSession来实现DAO组件的方式 - MyBatis提供的Starter会自动在Spring容器中配置SqlSession&#xff08;其实SqlSessionTemplate实现类&#xff09;、并将它注入其他组件&#xff08;如DAO组件&#xff09;- DAO组件可直接…

SpringBoot整合Mybatis-Plus分页插件的使用

&#x1f9d1;‍&#x1f4bb;作者名称&#xff1a;DaenCode &#x1f3a4;作者简介&#xff1a;CSDN实力新星&#xff0c;后端开发两年经验&#xff0c;曾担任甲方技术代表&#xff0c;业余独自创办智源恩创网络科技工作室。会点点Java相关技术栈、帆软报表、低代码平台快速开…

ExoPlayer实现本地视频播放器

最近单位项目不太忙&#xff0c;决定写个Demo实现一个自己的本地视频播放器&#xff0c;界面参考了完美视频播放器 本地视频播放器 架构简单&#xff0c;功能简单 MVVMkotlinexoplayer实现 当前实现点&#xff1a; 扫描本地视频并以文件夹&#xff08;视频列表&#xff09;形…

Cpp/Qt-day030919Qt

目录 完成文本编辑器的保存工作 头文件&#xff1a;widget.h: #ifndef WIDGET_H #define WIDGET_H#include <QWidget> #include <QFontDialog> //字体对话框 #include <QFont> //字体类 #include <QMessageBox> //消息对话框 #include <QDe…

Vue的详细教程--基础语法【上】

&#x1f973;&#x1f973;Welcome Huihuis Code World ! !&#x1f973;&#x1f973; 接下来看看由辉辉所写的关于Vue的相关操作吧 目录 &#x1f973;&#x1f973;Welcome Huihuis Code World ! !&#x1f973;&#x1f973; 一.插值 1.文本 2.html 3.属性&class绑…

Blender关键帧动画简明教程

Blender 3D 是一款能够创建令人惊叹的动画的免费软件。 Blender 中的大多数动画都使用所谓的关键帧。 Blender 中关键帧的介绍将涵盖开始制作动画所需的一切&#xff01; 推荐&#xff1a;用 NSDT编辑器 快速搭建可编程3D场景 1、什么是关键帧&#xff1f; 在计算机出现之前&a…

玩玩“小藤”开发者套件 Atlas 200I DK A2 之挂载 m2 硬盘

玩玩“小藤”开发者套件 Atlas 200I DK A2 之挂载 m2 硬盘 0. 背景1. 列出所有可用块设备的信息2. 格式化磁盘3. 创建 XFS 文件系统4. 挂载格式化的卷 0. 背景 总所周知&#xff0c;英伟达的GPU供不应求&#xff0c;还各种限制。华为推出了升腾AI可以提供AI算力&#xff0c;那…

【pytest】 标记冒烟用例 @pytest.mark.smoke

1. 使用 pytest.mark.smoke 标记用例 import pytest class Test_Smoke:def test_01(self):assert 112pytest.mark.smokedef test_02(self):assert 121pytest.mark.smokedef test_03(self):assert 1 2 3 2.配置文件pytest.ini [pytest] markers smoke 3. 运行指定标签 运…

从李佳琦到背后的商业逻辑再到游戏行业

引言 前阵子&#xff0c;李佳琦在直播间带货某牌子的眉笔时&#xff0c;被网友质疑越来越贵&#xff0c;对此李佳琦回应表示&#xff0c;79的眉笔不贵&#xff0c;国货品牌很难的&#xff0c;买不起的话&#xff0c;要找找自己的原因并反思这么多年有没有涨工资&#xff0c;有…

保存在本地的程序被删除了,咋恢复~

我在项目上&#xff0c;习惯在本地写一些工具代码。 大部分都是复制粘贴过来改吧改吧。 前段时间清理本地乱七八糟的程序&#xff0c;删了很多&#xff0c;当输入zlm**某个tcode后&#xff0c;提示没有&#xff0c;我擦发现&#xff0c;误删了~~ 好吧&#xff0c;难道只能重写&…

HTB靶机064-Arctic-WP

Arctic windows easy IP :10.10.10.11 端口扫描 简易端口扫描 ┌──(xavier㉿kali)-[~/Desktop/HTB/064-Arctic] └─$ sudo nmap -F 10.10.10.11 -T4 Starting Nmap 7.93 ( https://nmap.org ) at 2023-09-13 23:30 CST Nmap scan report for 10…

力扣 -- 394. 字符串解码

解题方法&#xff1a; 参考代码&#xff1a; class Solution{ public:string decodeString(string s){stack<string> sst;stack<int> dst;//防止字符串栈为空的时候再追加字符串到栈顶元素sst.push("");int n s.size();int i 0;while(i<n)//最好不…

JUC第四讲:Java中的锁

Java提供了种类丰富的锁&#xff0c;每种锁因其特性的不同&#xff0c;在适当的场景下能够展现出非常高的效率。本文是JUC第4讲&#xff0c;旨在对锁相关源码&#xff08;本文中的源码来自JDK 8和Netty 3.10.6&#xff09;、使用场景进行举例&#xff0c;为读者介绍主流锁的知识…

ROBOGUIDE教程:三维模型创建功能介绍与操作方法

目录 概述 模型创建方法 模型属性设置 其他类型模型创建 资源文件夹创建 安全围栏模型创建 概述 ROBOGUIDE软件除了可以从外部导入模型外&#xff0c;软件自身也可以创建一些简易的三维模型&#xff0c;在对FANUC机器人虚拟仿真或离线编程时&#xff0c;可以利用这个功能…

SOLIDWORKS Composer反转关键帧实现产品安装过程

SOLIDWORKS Composer 是一款被用来制作交互式产品说明书的工具&#xff0c;可以帮助我们对产品设定精确的机构动画&#xff0c;并能根据材质生成一定细节的渲染图像。 今天我们主要向大家讲解的是&#xff0c;利用SOLIDWORKS Composer关键帧反转实现产品动态的安装。 一般情况下…