【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;  // 输出:42
    
    std::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++、算法和编程的奥秘。祝您生活愉快,排便顺畅!
在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

靶机-Billu_b0x root 123456

查找靶机IP nmap查看开放端口22&#xff0c;80 目录扫描 查看网站&#xff0c;典型注入 phpmy 果然是登陆界面&#xff0c;不过不知道账户及密码 in.php php的配置信息&#xff0c;可以看看 add.php 上传文件目录&#xff0c;可以上传&#xff0c;不过没有回显 …

C# ObjectArx 绘制表格并设置单元格合并

第一行默认是标题&#xff0c;可设置行【RowType】进行设置类型 Document doc Application.DocumentManager.MdiActiveDocument;using (Transaction tr doc.TransactionManager.StartOpenCloseTransaction()){BlockTable bt tr.GetObject(doc.Database.BlockTableId, OpenMo…

UE4 添加按键输入事件 并在蓝图中使用按键输入节点

绑定按键 选择Edit/ProjectSettings/Engine/Input 在bindings中可以选择添加ActionMappings或则AxisMappings ActionMappings:按键事件&#xff0c;有按下和抬起两个事件&#xff0c;需要分别用两个键触发AxisMappings:输入事件&#xff0c;返回值为float&#xff0c;对于键盘…

Rust之构建命令行程序(三):重构改进模块化和错误处理

开发环境 Windows 10Rust 1.74.1 VS Code 1.85.1 项目工程 这次创建了新的工程minigrep. 重构改进模块化和错误处理 为了改进我们的程序&#xff0c;我们将修复与程序结构及其处理潜在错误的方式有关的四个问题。首先&#xff0c;我们的main函数现在执行两项任务:解析参数和…

一文了解Servlet

文章目录 1、什么是Servlet2、Servlet快速入门3、Servlet生命周期4、Servlet体系结构5、urlPatern配置6、XML编写Servlet 1、什么是Servlet Servlet是Java提供的一门动态web资源开发技术Servlet是JavaEE规范之一&#xff0c;其实就是一个接口&#xff0c;将来我们需要定义Serv…

Apache JMeter 5.6.3压力测试步骤详解

Apache JMeter 5.6.3压力测试步骤详解 压力测试简介软件测试概述性能测试性能测试指标性能指标推算web资源公式 1. 安装 Jmeter2. 创建测试任务2.1 创建线程组2.2 创建 HTTP 请求2.3 添加HTTP消息头管理器 3.添加查看结果监听器4. 执行测试5. 查看结果6. 非GUI模式测试7. 使用c…

CSS||Emmet语法

1、简介 ​ Emmet语法的前身是Zen coding,它使用缩写,来提高html/css的编写速度, Vscode内部已经集成该语法。 ​ 快速生成HTML结构语法 ​ 快速生成CSS样式语法 2、快速生成HTML结构语法 生成标签 直接输入标签名 按tab键即可 比如 div 然后tab 键&#xff0c; 就可以生成 <…

CSS 设置背景图片

文章目录 设置背景颜色设置背景图片背景图片偏移量计算原点背景图片尺寸设置背景图片位置设置背景图片重复方式设置背景范围设置背景图片是否跟随元素移动测试背景图片 本文概念部分参考&#xff1a;CSS背景background设置 设置背景颜色 background-color 设置背景颜色 设置…

UE5 独立程序的网络TCP/UDP服务器与客户端基础流程

引擎源码版&#xff0c;复制\Engine\Source\Programs\路径下的BlankProgram空项目示例。 重命名BlankProgram&#xff0c;例如CustomTcpProgram&#xff0c;并修改项目名称。 修改.Build.cs内容 修改Target.cs内容 修改Private文件夹内.h.cpp文件名并修改.cpp内容 刷新引擎 …

联想模拟器抓包

联想模拟器抓包 下载抓包工具配置代理并启动模拟器配置代理返回reqable查看抓包数据 下载抓包工具 reqable 配置代理并启动 模拟器配置代理 返回reqable查看抓包数据

定义公共样式css

index.less 文件 // 全局按钮颜色 btn_background: #005298; btn_border-color: #6fa18d;// 默认的 btn_border-color-highlight: #0598d3;// 高亮边框 btn_border-color-success: #36be7e;// 成功边框 btn_font_color: #fff;// 边框颜色 背景色 文字颜色 .btn_public(btn_bo…

外贸网站建设有哪些技巧?如何做海洋建站?

搭建外贸网站需要什么流程步骤&#xff1f;独立网站建站怎么做&#xff1f; 外贸网站的建设变得至关重要。一家成功的外贸企业需要一个强大而专业的在线存在&#xff0c;以便吸引国际客户。在这篇文章中&#xff0c;海洋建站将探讨一些关键的技巧&#xff0c;帮助您打造出色的…

Vg3225vfn压控晶体振荡器规格书

频率范围: 25mhz ~ 500mhz电源电压:3.3 V类型绝对拉力范围:50 10 6分钟。/ 25mhz至42.5 MHz50 MHz至85 MHz&#xff0c;100mhz ~ 170mhz:20 10 6最小&#xff0c;10 10 6分钟。/ 25mhz ~ 250mhz:10 10 6分钟。/ 250 MHz至500 MHz(85C最高)操作温度温度范围:-40℃~ 85℃温度…

低代码开发:解锁数字化转型新维度

在信息化浪潮中&#xff0c;企业正面临着前所未有的挑战与机遇。一方面&#xff0c;市场环境瞬息万变&#xff0c;业务需求迭代频繁&#xff0c;对快速应用开发提出了更高要求&#xff1b;另一方面&#xff0c;传统软件开发模式受限于高成本、长周期等瓶颈&#xff0c;难以满足…

C++、QT 数字合成游戏

一、项目介绍 数字合成游戏 基本要求&#xff1a; 1&#xff09;要求游戏界面简洁美观&#xff0c;且符合扫雷的游戏风格。 2&#xff09;需要有游戏操作或者规则说明&#xff0c;方便玩家上手。 3&#xff09;需具有开始游戏&#xff0c;暂停游戏&#xff0c;结束游戏等方便玩…

银河麒麟服务器操作系统搭建证书服务器并颁发可用于签名的证书步骤说明

银河麒麟服务器操作系统搭建证书服务器并颁发可用于签名的证书的方法与前面Centos7上&#xff08;centos7 使用openssl 配置证书服务器并颁发证书&#xff08;史上最详细版本&#xff09;_centos phpinfo显示的openssl配置项为/etc/pki/tls/openssl.c-CSDN博客&#xff09;是一…

某马头条——day04

自媒体文章自动审核 流程介绍 阿里云接口 这玩意必须要开通企业认证才能用&#xff0c;看看得了。 开通内容安全服务 文本审核接入指南_内容安全(Content Moderation)-阿里云帮助中心 文本审核接口返回内容 直接导入依赖并使用提供的实例代码 接口集成 接口测试 要在weme…

muduo网络库剖析——监听者Poller基类

muduo网络库剖析——监听者Poller基类 前情从muduo到my_muduo 概要框架与细节成员函数使用方法 源码结尾 前情 从muduo到my_muduo 作为一个宏大的、功能健全的muduo库&#xff0c;考虑的肯定是众多情况是否可以高效满足&#xff1b;而作为学习者&#xff0c;我们需要抽取其中…

新定义51单片机(RD8G37)实现测距测速仪

本文描述用新定义51单片机&#xff08;RD8G37&#xff09;超声波一体测距传感器实现简单的测距测速仪。 测距仪演示效果 新定义RD8G37Q48RJ开发板 超声波测距模块&#xff1a; 8位并口屏 1、main.c unsigned short timeConsuming0; unsigned int oldDistance;void rectClearS…

iOS上h5长按识别图片二维码,图片会默认放大,禁用这一默认行为

iOS上h5长按识别图片二维码&#xff0c;图片会默认放大&#xff0c;禁用这一默认行为 测试代码 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-widt…