【C++入门到精通】智能指针 auto_ptr、unique_ptr简介及C++模拟实现 [ C++入门 ]

在这里插入图片描述

阅读导航

  • 引言
  • 一、std::auto_ptr
    • 1. 简介
    • 2. 使用示例
    • 3. C++模拟实现
  • 二、std::unique_ptr
    • 1. 简介
    • 2. 使用示例
    • 3. C++模拟实现
  • 温馨提示

引言

在 C++ 中,智能指针是一种非常重要的概念,它能够帮助我们自动管理动态分配的内存,避免出现内存泄漏等问题。在上一篇文章中,我们了解了智能指针的基本概念和原理,本篇文章将继续介绍 auto_ptrunique_ptr 两种智能指针的概念及其在 C++ 中的模拟实现。通过学习这些内容,您将更好地理解智能指针的不同类型和使用场景,进一步提高程序的安全性和可靠性。让我们一起探索C++智能指针的精彩世界!

一、std::auto_ptr

🔴std::auto_ptr官方文档
在这里插入图片描述

1. 简介

std::auto_ptr 是 C++ 标准库中提供的一种智能指针类型,用于管理动态分配的内存资源。

std::auto_ptr 的主要特点是拥有所有权语义的转移。当一个 auto_ptr 对象拥有某个内存资源时,它可以将这个所有权转移给另一个 auto_ptr 对象。这意味着当一个 auto_ptr 对象被赋值给另一个 auto_ptr 对象或者被传递给一个函数时,原来的 auto_ptr 对象将不再拥有该资源,而是转移到了新的对象上

std::auto_ptr 类的定义在 <memory> 头文件中。使用 auto_ptr 需要包含该头文件,并使用 std 命名空间。

2. 使用示例

✅我们可以使用 auto_ptr 来管理动态分配的整型对象:

#include <iostream>
#include <memory>int main() {std::auto_ptr<int> ptr(new int(42));std::cout << *ptr << std::endl;  // 输出:42std::auto_ptr<int> ptr2 = ptr;  // 所有权转移std::cout << *ptr2 << std::endl;  // 输出:42// std::cout << *ptr << std::endl;  // 错误!ptr 不再拥有资源return 0;
}

🚨🚨注意当一个 auto_ptr 对象转移所有权后,原来的对象将变为一个空指针。这可能导致程序出现意外的行为,因此需要谨慎使用。此外,std::auto_ptr 并不支持数组类型的内存资源管理,它只适用于单个对象。如果需要管理动态分配的数组,应该使用其他智能指针类型,如 std::unique_ptrstd::shared_ptr

总之,std::auto_ptr 是 C++ 标准库中提供的一种智能指针类型,具有所有权转移的特性。然而,由于其存在一些潜在的问题,已经在 C++17 中被废弃,推荐使用更先进的智能指针类型来代替

3. C++模拟实现

template<class T>
class auto_ptr
{
public:// 构造函数,接受一个指向动态分配的资源的指针auto_ptr(T* ptr): _ptr(ptr){}// 析构函数,在对象销毁时释放资源~auto_ptr(){if (_ptr){cout << "delete:" << _ptr << endl;delete _ptr;}}// 拷贝构造函数,用于管理权转移auto_ptr(auto_ptr<T>& ap): _ptr(ap._ptr){ap._ptr = nullptr;}// 解引用操作符,返回所管理资源的引用T& operator*(){return *_ptr;}// 成员访问操作符,返回所管理资源的指针T* operator->(){return _ptr;}
private:T* _ptr;  // 指向动态分配的资源的指针
};

这段代码是一个简化版的 auto_ptr 类的实现,用于演示 auto_ptr 的基本工作原理。它是一个模板类,可以管理任意类型的动态分配的内存资源。

⭕该类包含了以下成员函数和成员变量:

  • 构造函数:接受一个指向动态分配的资源的指针,并将其存储在私有成员变量 _ptr 中。
  • 析构函数:在对象销毁时释放资源,即调用 delete 操作符删除 _ptr 指向的内存。
  • 拷贝构造函数:用于管理权转移,将另一个 auto_ptr 对象的资源转移到当前对象中,并将原对象的指针置为空。
  • operator*:用于解引用 auto_ptr 对象,返回所管理资源的引用。
  • operator->:用于访问 auto_ptr 所管理资源的成员。

🚨🚨再次提醒当一个 auto_ptr 对象转移所有权后,原来的对象将变为一个空指针。这可能导致程序出现意外的行为,因此需要谨慎使用

二、std::unique_ptr

🔴std::unique_ptr官方文档
在这里插入图片描述

1. 简介

std::unique_ptr 是 C++11 中引入的一种智能指针,它是一个轻量级的、不可拷贝的指针类型。与传统的裸指针不同,std::unique_ptr 通过 RAII 的方式来管理动态分配的内存资源,从而实现自动资源释放和防止内存泄漏

使用 std::unique_ptr 可以避免手动管理动态分配的内存资源,因为 std::unique_ptr 自身就拥有资源的所有权,当 std::unique_ptr 被销毁时,它所管理的资源也会被自动释放。这使得代码更加简洁、安全和易于维护

std::unique_ptr 有以下几个主要特点:

  1. 不支持拷贝和赋值操作,即不能直接复制或赋值一个 std::unique_ptr 对象,只能通过移动语义或者 std::move 函数来转移资源的所有权;
  2. 在默认情况下,std::unique_ptr 使用 delete 操作符来释放所管理的资源,但也可以通过自定义删除器来实现对资源的自定义释放操作;
  3. 支持使用 lambda 表达式来实现自定义删除器,从而更加灵活地管理资源。

2. 使用示例

下面是一个简单的示例,演示了 std::unique_ptr 的基本使用方法:

#include <iostream>
#include <memory>int main()
{// 使用 std::unique_ptr 来管理动态分配的 int 类型对象std::unique_ptr<int> uptr(new int(42));// 解引用操作符,返回所管理资源的引用std::cout << *uptr << std::endl;// 成员访问操作符,返回所管理资源的指针int* p = uptr.get();std::cout << *p << std::endl;// 试图复制或赋值 unique_ptr 对象会编译错误// std::unique_ptr<int> uptr2 = uptr; // Error// 转移资源所有权std::unique_ptr<int> uptr2 = std::move(uptr);std::cout << *uptr2 << std::endl;return 0;
}

输出结果为

42
42
42

🚨🚨注意:由于 std::unique_ptr 是一个模板类,可以管理任意类型的动态分配的内存资源,因此使用时需要显式指定模板参数。另外,对于数组的动态分配内存资源的管理,建议使用 std::unique_ptr 的数组版本 std::unique_ptr<T[]>

3. C++模拟实现

template<class T>
class unique_ptr
{
public:// 构造函数,接受一个裸指针作为参数unique_ptr(T* ptr):_ptr(ptr){}// 析构函数,释放资源~unique_ptr(){if (_ptr){cout << "delete:" << _ptr << endl;delete _ptr;}}// 重载解引用操作符,返回资源的引用T& operator*(){return *_ptr;}// 重载成员访问操作符,返回资源的指针T* operator->(){return _ptr;}// 防止拷贝和赋值// C++11思路:直接将拷贝构造函数和赋值运算符声明为删除函数unique_ptr(const unique_ptr<T>& up) = delete;unique_ptr<T>& operator=(const unique_ptr<T>& up) = delete;// 防止拷贝和赋值// C++98思路:只声明不实现,但是用的人可能会在外部强行定义,所以再加一条,声明为私有// private:// unique_ptr(const unique_ptr<T>& up);// unique_ptr<T>& operator=(const unique_ptr<T>& up);private:T* _ptr;
};

🚩这段代码实现了一个简化版的 unique_ptr 类,具有管理动态资源的能力,并防止了拷贝和赋值操作。注释中详细解释了每个函数的作用和实现原理,以及两种防止拷贝和赋值的方式(C++11 和 C++98 思路)

温馨提示

感谢您对博主文章的关注与支持!另外,我计划在未来的更新中持续探讨与本文相关的内容,会为您带来更多关于C++以及编程技术问题的深入解析、应用案例和趣味玩法等。请继续关注博主的更新,不要错过任何精彩内容!

再次感谢您的支持和关注。期待与您建立更紧密的互动,共同探索C++、算法和编程的奥秘。祝您生活愉快,排便顺畅!
在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

YOLOv5改进 | 检测头篇 | 利用DynamicHead增加辅助检测头进行针对性检测(让小目标无所遁形)

一、本文介绍 本文给大家带来的改进机制是针对性的改进,针对于小目标检测增加P2层,利用DynamicHead(原版本一比一复现,全网独一份,不同于网上魔改版本)进行检测,其中我们增加P2层其拥有更高的分辨率,这使得模型能够更好地捕捉到小尺寸目标的细节。在这些的基础上配合Dyn…

使用@Slf4j后引入log,idea标红

引入Slf4j注解 idea标红Cannot resolve symbol ‘log’ 引入Lombok插件 如果在Marketplace查不到时&#xff0c;不妨关闭菜单再打开试下

Qt 状态机框架:The State Machine Framework (二)

传送门: Qt 状态机框架:The State Machine Framework (一) Qt 状态机框架:The State Machine Framework (二) 1、利用并行态避免态的组合爆炸 假设您想在单个状态机中对汽车的一组互斥属性进行建模。假设我们感兴趣的属性是干净与肮脏&#xff0c;以及移动与不移动。需要四个…

汇川PLC与工业远程透传模块远程上下载程序

准备工作 一台可联网操作的电脑一台单网口的远程透传网关及博达远程透传配置工具网线一条&#xff0c;用于实现网络连接和连接PLC一台汇川 H5U-1614MTD-A8 PLC及其编程软件一张4G卡或WIFI天线实现通讯(使用4G联网则插入4G SIM卡&#xff0c;WIFI联网则将WIFI天线插入USB口&…

数据守护盾牌:敏感数据扫描与脱敏,让安全合规无忧

前言 在信息时代&#xff0c;数据已经成为企业和组织的核心资产&#xff0c;其价值与日俱增。然而&#xff0c;随着数据使用的普及和复杂度的提升&#xff0c;数据安全与合规问题也变得越来越突出。敏感数据的保护显得尤为重要&#xff0c;因为这些数据一旦泄露或被不当使用&a…

AI教我学编程之C#类的基本概念(1)

前言 在AI教我学编程之C#类型 中&#xff0c;我们学习了C#类型的的基础知识&#xff0c;而类正是类型的一种. 目录 区分类和类型 什么是类&#xff1f; 对话AI 追问 实操 追踪属性的使用 AI登场 逐步推进 提出疑问 药不能停 终于实现 探索事件的使用 异步/交互操作 耗时操…

【前后端的那些事】评论功能实现

文章目录 聊天模块1. 数据库表2. 后端初始化2.1 controller2.2 service2.3 dao2.4 mapper 3. 前端初始化3.1 路由创建3.2 目录创建3.3 tailwindCSS安装 4. tailwindUI5. 前端代码编写 前言&#xff1a;最近写项目&#xff0c;发现了一些很有意思的功能&#xff0c;想写文章&…

前端——框架——Vue

提示&#xff1a; 本文只是从宏观角度简要地梳理一遍vue3&#xff0c;不至于说学得乱七八糟、一头雾水、不知南北&#xff0c;如果要上手写代码、撸细节&#xff0c;可以根据文中的关键词去查找资料 简问简答&#xff1a; vue.js是指vue3还是vue2&#xff1f; Vue.js通常指的是…

回馈科教,非凸科技助力第48届ICPC亚洲区决赛

1月12日-14日&#xff0c;“华为杯”第48届国际大学生程序设计竞赛&#xff08;ICPC&#xff09;亚洲区决赛在上海大学成功举办。非凸科技作为此次赛事的支持方之一&#xff0c;希望携手各方共同推动计算机科学和技术的发展。 这是一场智慧的巅峰对决&#xff0c;320支优秀队伍…

K8s-架构

一、K8s节点划分 K8s集群包含Master(控制节点)和Node(工作节点)&#xff0c;应用部署在Node节点上。 集群架构图&#xff1a; 二、Master节点 Master节点分成四个组件&#xff1a;scheduler、ApiServer、Controller Manager、ETCD。类似三层结构&#xff0c;controller&#…

20240117-【UNITY 学习】增加墙跑功能和跳墙功能

替换脚本PlayerCam_01.cs using System.Collections; using System.Collections.Generic; using UnityEngine; using DG.Tweening;public class PlayerCam_02 : MonoBehaviour {// 视觉灵敏度参数public float sensX 400;public float sensY 400;// 视角垂直旋转角度限制publ…

redis安装-Linux为例

可以下载一个Shell或者MobaXterm工具&#xff0c;便于操作 在redis官网下载压缩包 开始安装 安装依赖 yum install -y gcc tcl切换目录 切换目录后直接把redis安装包拖到/user/local/src/下 cd /user/local/src/解压然后安装 #解压 tar -zxvf redis-7.2.4.tar.gz #安装 …