【C++】智能指针(一)

news2024/11/16 15:37:34

这篇文章介绍下C++的智能指针,当然,可能没有你想的那么智能。

为什么需要智能指针1

void remodel(string& str)
{
    string* ps = new string(str);
    str = *ps;
    return;
}

这里不讨论这个函数有没有意义,在这段代码中,很明显,ps没有得到释放。函数的生命周期结束时,临时变量strps都会被销毁,但ps分配的内存还在内存空间里。正确的写法如下:

void remodel(string& str)
{
    string* ps = new string(str);
    str = *ps;
    delete ps;
    return;
}

不需要使用delete[],因为是C++的内置结构。

如果ps有一个析构函数,此函数会在它过期时删除指向的内存那可太好了。但ps只是一个指针,不是对象。而智能指针的思想就是设计一个模板类,代替指针实现上述功能。

auto_ptr、unique_ptr

C++98提出了模板类auto_ptr,但是这个方案在C++11被废弃了,废弃的原因之后我们会讨论,先介绍下这个最早的智能指针。

为了介绍auto_ptr,我们先设计一个类,当其构造函数和析构函数被调用会打印点什么。

class SmartPointer
{
public:
    SmartPointer(string s);
    ~SmartPointer();
};

SmartPointer::SmartPointer(string s)
{
    cout << "SmartPointer Created!" << endl;
}

SmartPointer::~SmartPointer()
{
    cout << "SmartPointer Deleted!" << endl;
}

如下代码会泄露内存,因为SmartPointer的析构函数没有被调用。

int main()
{
    string myStr = "love";
    auto* ps = new SmartPointer(myStr);
}

泄露
使用智能指针,需要包含memory头文件,其格式也和正常的指针不太一样。

auto_ptr<SmartPointer> ps(new SmartPointer("myStr"));

看打印结果,这次析构函数得到了调用。
auto_ptr
智能指针的构造函数可以接受常规指针,但是是explicit的,也就意味着无法进行隐式转换。

    auto* ps = new SmartPointer("C++");    
    auto_ptr<SmartPointer> spp = ps; //error
    auto_ptr<SmartPointer> spp2(ps);

接下来讨论一个问题:共享,这是一个智能指针需要处理但是普通指针不需要处理的问题:

    auto_ptr<SmartPointer> sps(new SmartPointer("myStr"));
    auto_ptr<SmartPointer> sps2;
    sps2 = sps;

按照智能指针的设计,两个指针离开生命周期都会释放对应的内存,这就意味着sps2释放的内存是空的。(普通指针不会释放内存所以不会有这个问题,但delete也只能写一个)

有两种办法解决这个问题:

建立所有权概念(ownership)

某些对象只允许一个智能指针拥有它,且如上的赋值操作会转让所有权。这办法应用于auto_ptrunique_ptr,但后者更为严格。

我们为类增加了一个成员变量a,并赋默认值1,然后把上面的代码继续写下去:

    auto_ptr<SmartPointer> sps(new SmartPointer("myStr"));
    auto_ptr<SmartPointer> sps2;
    sps2 = sps;
    cout << sps->a << endl;

代码会引发segment fault,因为sps已经将所有权移交给sps2,现在的sps是空指针。访问空指针的成员变量会出错。不过有一点,如果这里是执行一个成员函数,函数只打印一句话,就没有这个问题,不明白为什么。

unique_ptr

unique_ptr的策略类似于auto_ptr,不过程序会在编译的时候就报错,而不是等到运行的时候再出问题。如果你的IDE足够智能,也会给出提示:
提示

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

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

相关文章

arduino 简易智能花盆

编辑器&#xff1a;arduino IDE 主板&#xff1a;arduino uno 传感器&#xff1a; 0.96寸的OLED屏&#xff08;四脚&#xff09; 声音模块 土壤温湿度模块 DS18B20温度模块&#xff08;这里用到防水的&#xff09; 光敏电阻模块&#xff08;买成三脚的了只能显示高低&#x…

state 和 props 有什么区别?

一、state 一个组件的显示形态可以由数据状态和外部参数所决定&#xff0c;而数据状态就是 state&#xff0c;一般在 constructor 中初始化 当需要修改里面的值的状态需要通过调用 setState 来改变&#xff0c;从而达到更新组件内部数据的作用&#xff0c;并且重新调用组件 r…

Linux操作系统下对c语言程序的编译和执行过程gcc,编译链接过程

目录 1.gcc,g,gdb安装 2.gcc分布编译链接 3.编译链接过程 4.执行 4.1 如何执行 4.2 两步执行与一步执行 4.3 多文件的编译执行 1.gcc,g,gdb安装 命令行写gcc,g,gdb根据提示安装:sudo apt install gcc/g/gdb 2.gcc分布编译链接 (1)预编译: gcc -E main.c -o main.i (2)…

视频剪辑技巧:探索画中画视频剪辑,如何制作引人入胜的视觉效果

在视频制作领域&#xff0c;画中画视频剪辑是一种备受瞩目的技术&#xff0c;它可以将多个视频画面叠加在一起&#xff0c;形成一种独特的视觉效果。这种剪辑技巧可以让观众同时看到两个或多个视频片段&#xff0c;创造出一种引人入胜的视觉体验。在开始画中画视频剪辑之前&…

C++算法:矩阵中的最长递增路径

涉及知识点 拓扑排序 题目 给定一个 m x n 整数矩阵 matrix &#xff0c;找出其中 最长递增路径 的长度。 对于每个单元格&#xff0c;你可以往上&#xff0c;下&#xff0c;左&#xff0c;右四个方向移动。 你 不能 在 对角线 方向上移动或移动到 边界外&#xff08;即不允…

工商业微电网储能盈利方式研究笔记

1. 光储微电网 1.1. 关于光储微电网 光储微电网可以看成是一组由分布式光伏、储能装置、本地负荷组成的包括发、输、配、用管理系统在内的小型局域电网&#xff0c;并通过唯一的公共连接点接入大电网&#xff0c;既可以并网运行也可以独立运行。 发展分布式光储微电网的意义…

STM32 X-CUBE-AI:Pytorch模型部署全流程

文章目录 概要版本&#xff1a;参考资料STM32CUBEAI安装CUBEAI模型支持LSTM模型转换注意事项模型转换模型应用1 错误类型及代码2 模型创建和初始化3 获取输入输出数据变量4 获取模型前馈输出模型应用小结 小结 概要 STM32 CUBE MX扩展包&#xff1a;X-CUBE-AI部署流程&#xf…

ROS 多级tf坐标转换

题目 现有一移动机器人&#xff0c;该机器人的基坐标系为“base_link”&#xff0c;机器人包含3个子坐标系分别为“joint1”&#xff0c;“joint2”&#xff0c;“joint3”。 要求&#xff1a;利用多坐标转换&#xff0c;实现joint1下的坐标向joint2下的坐标转换&#xff0c;…

AMD64内存属性详解

本文参考文档为AMD64 Architecture Programmer’s Manual Volume 2: System Programming&#xff0c;版本号3.41&#xff0c;这不是对原英文文档的翻译&#xff0c;但是所有内容的排版都是根据原手册的排版来的&#xff0c;如有与官方文档冲突的内容&#xff0c;以官方文档为准…

[LeetCode]-622. 设计循环队列

目录 662. 设计循环队列 题目 思路 代码 662. 设计循环队列 622. 设计循环队列 - 力扣&#xff08;LeetCode&#xff09;https://leetcode.cn/problems/design-circular-queue/ 题目 设计你的循环队列实现。 循环队列是一种线性数据结构&#xff0c;其操作表现基于 FIFO&…

推荐几个宝藏app

立冬后&#xff0c;真尼玛冷&#xff0c;哎&#xff01;记得多穿点衣服呀&#xff0c;老铁们&#xff01;&#xff01; GKD 去广告神器 下载网址&#xff1a;https://github.com/gkd-kit/gkd 特性&#xff1a; 它不仅支持跳过开屏广告&#xff0c;还支持跳过弹窗广告等&#xf…

Shopee活动取消规则是什么?shopee官方促销活动怎么取消?

作为一家知名的电商平台&#xff0c;shopee官方对于消费者取消促销活动的请求给予了相应的规定和处理流程。 shopee活动取消规则是什么&#xff1f; 首先&#xff0c;消费者应该明确了解虾皮的促销活动取消规则。根据虾皮的官方规定&#xff0c;消费者在参与促销活动之前&…

公司注册股东选择几个人合适?

创业初期很多创业者都会选择有注册有限责任公司&#xff0c;有限责任由五十个以下的股东出资设立&#xff0c;每个股东以其所认缴的出资额为限对公司承担有限责任。那么问题来了股东人数选择几个最合适呢&#xff0c;下面上海注册公司网&#xff08;www.91kaiye.cn&#xff09;…

部署ruoyi-vue-plus和ruoyi-app

nginx.conf worker_processes 1;error_log /var/log/nginx/error.log warn; pid /var/run/nginx.pid;events {worker_connections 1024; }http {include mime.types;default_type application/octet-stream;sendfile on;keepalive_timeout 65;# 限制…

人工智能基础——Python:运行效率与时间复杂度

人工智能的学习之路非常漫长&#xff0c;不少人因为学习路线不对或者学习内容不够专业而举步难行。不过别担心&#xff0c;我为大家整理了一份600多G的学习资源&#xff0c;基本上涵盖了人工智能学习的所有内容。点击下方链接,0元进群领取学习资源,让你的学习之路更加顺畅!记得…

15 # 手写 throttle 节流方法

什么是节流 节流是限制事件触发的频率&#xff0c;当持续触发事件时&#xff0c;在一定时间内只执行一次事件&#xff0c;这个效果跟英雄联盟里的闪现技能释放差不多。 函数防抖关注一定时间连续触发的事件只在最后执行一次&#xff0c;而函数节流侧重于一段时间内只执行一次…

快速排序实现方法(剑指offer思路)

快速排序思想 从参与排序的数组中&#xff0c;选择一个数&#xff0c;把小于这个数的放在左边&#xff0c;大于这个数的放在右边&#xff0c;然后递归操作。 实现算法思路 选择最后一个当作参考值&#xff0c;使用small索引当作比这个数小的下标值遍历数组&#xff0c;如果小…

MySQL查询时间处理相关函数与方法实践笔记

1. 实践案例 在查询mysql数据库获取数据时&#xff0c;有这样一个需求&#xff1a;按每30分钟分组获取电量数据&#xff0c;形成1天48个数据点。 方法一&#xff1a; select hour(a.CreateTime) 时点,case when MINUTE(a.CreateTime)<30 then 1 else 2 end 半小时,sum(a…

思维模型 斯金纳箱原理

本系列文章 主要是 分享 思维模型&#xff0c;涉及各个领域&#xff0c;重在提升认知。通过合理奖惩&#xff0c;塑造行为&#xff0c;此名为“学习”。 1 斯金纳箱原理的应用 1.1 斯金纳箱在游戏设计中的应用-《糖果传奇》 《糖果传奇》是一款由 King 开发的三消游戏&#x…

基于SSM的培训机构运营系统

末尾获取源码 开发语言&#xff1a;Java Java开发工具&#xff1a;JDK1.8 后端框架&#xff1a;SSM 前端&#xff1a;Vue 数据库&#xff1a;MySQL5.7和Navicat管理工具结合 服务器&#xff1a;Tomcat8.5 开发软件&#xff1a;IDEA / Eclipse 是否Maven项目&#xff1a;是 目录…