了解常用智能指针

智能指针

1、概念

C++中引入智能指针的主要目的是为了解决内存管理的问题,传统的指针(裸指针)在使用时需要手动分配和释放内存,容易出现内存泄漏悬挂指针等问题。智能指针通过封装裸指针,并提供自动内存管理功能,使得内存资源可以更安全、高效地管理。

2、内存泄漏

有人说,我每次记得将new过的指针delete,是不是就可以不使用智能指针了呢?智能指针怪麻烦的!但有些时候指针不是你想delete他就真的delete了

我举个例子:

#include <iostream>
#include <string>
#include <memory>using namespace std;// 1、动态分配内存,没有释放就return
void memoryLeak1() {string *str = new string("动态分配内存!");return;
}// 2、动态分配内存,虽然有些释放内存的代码,但是被半路截胡return了
int memoryLeak2() {string *str = new string("内存泄露!");// ...此处省略一万行代码// 发生某些异常,需要结束函数if (1) {return -1;}// 另外,使用try、catch结束函数,也会造成内存泄漏!delete str;	// 虽然写了释放内存的代码,但是遭到函数中段返回,使得指针没有得到释放return 1;
}int main(void) {memoryLeak1();memoryLeak2();return 0;
} 

对于第二种内存泄漏,在代码中发现异常需要结束函数,后面的delete并没有执行,此时指针并没有释放,即会导致内存泄漏。

3、智能指针原理

智能指针本质是一个类模板它可以创建任意的类型的指针对象,当智能指针对象使用完后,对象就会自动调用析构函数去释放该指针所指向的空间。如下所示:

在这里插入图片描述

这样即可自己写一个简易的智能指针:

#pragma once
#include <iostream>
template<class T>
class smartptr
{
public:smartptr(T* ptr = nullptr):_ptr(ptr){};~smartptr(){std::cout << "ptr delete..." << std::endl;if (_ptr)delete _ptr;}private:T* _ptr;
};

测试:

#include "smartpoint.h"
void test1() 
{smartptr<int> ptr1;smartptr<double> ptr2;smartptr<bool> ptr3;
}int main()
{test1();return 0;
}

结果:
在这里插入图片描述

4、常见智能指针

1、auto_ptr

std::auto_ptr是C++98标准中提供的智能指针,它是独占式智能指针,已经过时,在这里不深究

2、unique_ptr

std::unique_ptr是C++11标准引入的智能指针,其核心思想是独占所有权(exclusive ownership)和资源管理的责任。

核心思想(禁止拷贝和可以Move):

  • 独占所有权:std::unique_ptr独占所管理的指针资源,同一时间只能有一个std::unique_ptr拥有该资源。当std::unique_ptr被销毁或转移所有权时,它会自动释放所管理的资源,确保资源在适当的时候被正确释放,避免资源泄漏。
  • 确保资源的释放:std::unique_ptr通过在析构函数中自动调用delete来释放所管理的资源。这意味着,无论是通过正常的控制流还是异常的控制流,只要std::unique_ptr被销毁,资源都会得到释放,避免了手动释放资源的繁琐和可能的遗漏。
  • 禁止拷贝:std::unique_ptr禁止拷贝构造函数和拷贝赋值运算符的使用,以确保同一时间只有一个std::unique_ptr拥有资源的所有权。这样可以防止多个智能指针同时管理同一块资源,避免了资源的重复释放和悬挂指针的问题。
  • 支持移动Move语义:std::unique_ptr支持移动构造函数和移动赋值运算符,允许资源的所有权从一个std::unique_ptr对象转移到另一个对象,避免了资源的不必要拷贝。

unique_ptr创建:

int main()
{{// std::unique_ptr<Entity> entity = new Entity(); // 错误// std::unique_ptr<Entity> entity(new Entity()); // 普通指针使用方法std::unique_ptr<Entity> entity = std::make_unique<Entity>(); // 最好使用这种// std::unique_ptr<Entity> e0 = entity; // 错误entity->Print();}return 0;
}
class Entity
{
public:Entity(){std::cout << "Create Entity!" << std::endl;}~Entity(){std::cout << "Destroyed Entity!" << std::endl;}void Print() {};
};

离开作用域前,打印Create Entity!;离开作用域后,打印Destroyed Entity!

查看unique_ptr函数,会发现拷贝和构造函数都被删除,这是编译器防止程序员自掘坟墓,做出的提示!

在这里插入图片描述

3、shared_ptr

使用unique_ptr最大的缺点即是不能拷贝指针,所以,如果你喜欢分享,可以使用shared_ptr来弥补缺陷!

核心思想:

当复制或拷贝时,引用计数加1,当智能指针析构时,引用计数减1,如果计数为零,代表已经没有指针指向这块内存,那么我们就释放它!这就是 shared_ptr 采用的策略!

int main()
{// test1();{std::shared_ptr<Entity> sharedEntity = std::make_shared<Entity>();std::shared_ptr<Entity> e0 = sharedEntity; // 正确,增加引用计数entity->Print();}return 0;
}

4、weak_ptr

可以与shared一起使用,对于shared来说,它不会增加计数器,

int main()
{{std::shared_ptr<Entity> sharedEntity = std::make_shared<Entity>();std::weak_ptr<Entity> e0 = sharedEntity; // 不会增加计数器entity->Print();}return 0;
}

常见的智能指针即这几种,后面可能会手写智能指针,看后面更新吧!


参考
cpp_learners
努力学习的少年
哔哩哔哩

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

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

相关文章

一、Socket创建和连接

C网络编程&#xff08;asio&#xff09; 文章目录 C网络编程&#xff08;asio&#xff09;1、Asio概述2、网络编程基本流程2、创建socket3、创建监听socket4、绑定accpet监听套接字5、连接指定的端点6、服务器接收连接 点击查看代码 1、Asio概述 ​ Asio起源于Boost库&#xf…

shell编程(三)—— 运算符

和其他编程语言一样&#xff0c;bash也有多种类型的运算符&#xff0c;本篇对bash的相关运算符做简单介绍。 一、运算符 1.1 算术运算符 常见的算术运算符&#xff0c;如加&#xff08;&#xff09;、减&#xff08;-&#xff09;、乘&#xff08;*&#xff09;、除&#xf…

OpenGauss数据库-4.表的创建、修改与删除

第1关&#xff1a;创建表 gsql -d postgres -U gaussdb -W passwd123123 create database testdb; \c testdb; passwd123123 create table test_table (test_id integer not null,test_info char(36)); 第2关&#xff1a;修改表 gsql -d testsb -U gaussdb -W passwd123123 …

Flink 基于 TDMQ Apache Pulsar 的离线场景使用实践

背景 Apache Flink 是一个开源的流处理和批处理框架&#xff0c;具有高吞吐量、低延迟的流式引擎&#xff0c;支持事件时间处理和状态管理&#xff0c;以及确保在机器故障时的容错性和一次性语义。Flink 的核心是一个分布式流数据处理引擎&#xff0c;支持 Java、Scala、Pytho…

DeepSORT(目标跟踪算法)中的马氏距离详解(很详细)

DeepSORT&#xff08;目标跟踪算法&#xff09;中的马氏距离详解&#xff08;很详细&#xff09; flyfish 马氏距离的公式是由印度统计学家【普拉萨纳钱德拉马哈拉诺比斯&#xff08;Prasanta Chandra Mahalanobis&#xff09;】&#xff09;&#xff08;好长的名字&#xff…

怎样快速获取Vmware VCP 证书,线上考试,voucher报名优惠

之前考一个VCP证书&#xff0c;要花大一万的费用&#xff0c;可贵了&#xff0c;考试费不贵&#xff0c;贵就贵在培训费&#xff0c;要拿到证书&#xff0c;必须交培训费&#xff0c;即使vmware你玩的很溜&#xff0c;不需要再培训了&#xff0c;但是一笔贵到肉疼的培训费你得拿…

哈希表与哈希扩容

一&#xff0c;哈希表 哈希表简单的理解&#xff1a;在记录的存储位置和它的关键字之间建立一个确定的对应关系f&#xff0c;使每个关键字和结构中一个唯一的存储位置相对应。 哈希表基于数组的&#xff0c;正因为数组创建后难于扩展某些哈希表被基本填满时&#xff0c;性能下…

JS类型转换面试题:[] == ![] 为true?

前言 OK,又是在学习的路上遇到了难点&#xff0c;今天拿来分享一哈。ok&#xff0c;话不多说&#xff0c;开始分享。 下面是一道面试题 console.log([]![])你觉得上面的值打印为多少&#xff1f;我告诉你&#xff0c;打印的结果是true。如果你是猜对的或者不会可以看看我对这…

Capture One 23 软件安装教程、附安装包下载

Capture One Capture One 23 是一款功能极为全面的图片处理软件&#xff0c;为用户提供了真正的逼真色彩处理和无缝衔接的编辑体验&#xff0c;以及业界最快的联机拍摄功能&#xff0c;可以满足用户在图像创作上的所有功能&#xff0c;如创作全景拼接大图、高级色彩调整、遮罩…

0605-JavaSE-单例模式-饿懒汉模式

​​​​​​​ 不能放在方法里面&#xff08;因为每个线程调用都会在方法里面实例化一个locker对象&#xff0c;但不属于同一个对象&#xff09;&#xff0c;然后要用static修饰成静态变量才会起到效果 //单例设计模式 //饿汉模式&#xff1a;在加载类的时候就已经开始创建 /…

Opencv基本操作

Opencv基本操作 导入并使用opencv进行图像与视频的基本处理 opencv读取的格式是BGR import cv2 #opencv读取的格式是BGR import numpy import matplotlib.pyplot as plt %matplotlib inline图像读取 通过cv2.imread()来加载指定位置的图像信息。 img cv2.imread(./res/ca…

3-哈希表-51-四数相加 II-LeetCode454

3-哈希表-51-四数相加 II-LeetCode454 LeetCode: 题目序号454 更多内容欢迎关注我&#xff08;持续更新中&#xff0c;欢迎Star✨&#xff09; Github&#xff1a;CodeZeng1998/Java-Developer-Work-Note 技术公众号&#xff1a;CodeZeng1998&#xff08;纯纯技术文&#xff…

基本表的定义:创建表、修改表、删除表

一、创建数据库与打开数据库 学生选课数据库 学生&#xff08;学号&#xff0c;姓名&#xff0c;性别&#xff0c;出生时间&#xff0c;所在系&#xff09; 课程&#xff08;课程编号&#xff0c;课程名&#xff0c;先修课程号&#xff09; 选课&#xff08;学号&#xff0…

js调试过程中修改变量值

1.在想要变更的地方添加断点 2.添加监视表达式 3.执行网页代码&#xff0c;当执行到断点处则会停止 4.点击执行下一步&#xff0c;则会执行监视表达式

Linux下打印封装_统计函数执行时间_线程号时间戳打印

统计函数执行时间&#xff08;多线程环境下统计结果不准&#xff09; // 无返回值 #define FUNC_EXEC_TIME_NORET(fun,promote) ({ \ unsigned long long timeDelta 0; \ struct timespec t1 {0}; \ struct timespec t2 {0}; \ clock_gettime(CLOCK_MONOTONIC, &t1); \ …

高考分数查询结果自动推送至微信(卷II)

祝各位端午节安康&#xff01;只要心中无结&#xff0c;每天都是节&#xff0c;开心最重要&#xff01; 在上一篇文章高考分数查询结果自动推送至微信&#xff08;卷Ⅰ&#xff09;-CSDN博客中谈了思路&#xff0c;今天具体实现。文中将敏感信息已做处理&#xff0c;读者根据自…

React+TS前台项目实战(四)-- layout整体布局搭建

文章目录 前言一、Layout组件代码注释说明二、Content全局组件注释说明三、Header基础布局组件1. Header父级组件注释说明2. NavMenu导航子组件详细说明 四、效果展示总结 前言 本文主要讲Layout整体布局的构建以及全局内容盒子Content组件的使用。还包括了导航栏组件的基本封…

未来几年,同样的性能,推理功耗降低为现在的几万分之一,有可能吗

未来几年,同样的性能,推理功耗降低为现在的几万分之一,有可能吗 一.数据二.抓取LLM排行榜,相同的MMLU精度,模型参数量缩减倍数三.其它 有人说未来几年,推理功耗能降低为现在的几万分之一,好奇怎么能做到呢 一.数据 二.抓取LLM排行榜,相同的MMLU精度,模型参数量缩减倍数 import…

spool 管道 小文件 mknod

Spool File In SQL*PLUS in Multiple Small Files ? (Doc ID 2152654.1)​编辑To Bottom In this Document Goal Solution APPLIES TO: Oracle Database - Enterprise Edition - Version 10.2.0.1 to 12.1.0.2 [Release 10.2 to 12.1] Oracle Database Cloud Schema Service…

从零开始搭建Electron项目之运行例程

最好的学习方式就是&#xff1a;给一段能够运行的代码示例。 本文给出了例程资源&#xff0c;以及运行的步骤。 在国内开发electron有一点特别不好&#xff0c;就是如果不爬梯子&#xff0c;下载依赖容易出错。 一、例程资源 到如下路径下载例程到本地。 GitCode - 全球开发者…