了解常用智能指针

news2024/10/5 9:32:18

智能指针

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.coloradmin.cn/o/1810004.html

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

相关文章

端午安康,最真挚的祝福送最“粽”要的人

端午节&#xff0c;又称端阳节、龙舟节、重五节、天中节等&#xff0c;是集拜神祭祖、祈福辟邪、欢庆娱乐及饮食为一体的民俗大节&#xff0c;与春节、清明节、中秋节并称为中国四大传统节日&#xff0c;2008年被列为国家法定节假日&#xff0c;2009年9月端午节成为中国首个入选…

笔记 | 软件工程04:软件项目管理

1 软件项目及其特点 1.1 什么是项目 1.2 项目特点 1.3 影响项目成功的因素 1.4 什么是软件项目 针对软件这一特定产品和服务的项目努力开展“软件开发活动",&#xff08;理解&#xff1a;软件项目是一种活动&#xff09; 1.5 软件项目的特点 1.6 军用软件项目的特点 2 …

有点好玩的python运维脚本

python运维脚本 1. 常用端口扫描2. 文件整理 1. 常用端口扫描 在计算机网络中&#xff0c;端口是一个通信端点&#xff0c;允许不同的进程或服务通过网络连接和交换数据。端口通过数值来标识&#xff0c;并与特定的协议相关联。未采取适当安全措施而保持端口开放&#xff0c;可…

ICRA 2024:北京工业大学马楠教授联合中科原动力公司推出番茄采摘自主机器人AHPPEBot,实现32.46秒快速准确采摘

当前&#xff0c;农业生产正深受劳动力短缺困扰&#xff0c;这一现状对生产规模的进一步拓展构成了严重制约。为了突破这一瓶颈&#xff0c;实施自动化已成为提升农业生产力的关键途径&#xff0c;这也使得机器人采收技术备受关注。 现今的机器人采收系统普遍采用先进感知方法&…

linux 网桥学习

前言&#xff1a; 本文来学习一下linux网桥概念和网桥配置 1. linux网桥概念 网桥&#xff0c;类似于中继器&#xff0c;连接局域网中两个或者多个网段。它与中继器的不同之处就在于它能够解析它收发的数据&#xff0c;读取目标地址信息&#xff08;MAC&#xff09;&#xff…

技术玩家实现在不支持的CPU上运行 Windows 10 22H2

最近&#xff0c;AMD 悄然确认&#xff0c;其新款 Ryzen AI 300 系列 APU 将不再为 Windows 10 制作芯片组驱动程序&#xff0c;因为它将终止对Windows 10操作系统的支持&#xff0c;尽管它完全有能力这样做。这意味着想要获得官方驱动程序支持的用户必须在其上运行 Windows 11…

darts 时序预测入门

darts是一个强大而易用的Python时间序列建模工具包。在github上目前拥有超过7k颗stars。 它主要支持以下任务: 时间序列预测 (包含 ARIMA, LightGBM模型, TCN, N-BEATS, TFT, DLinear, TiDE等等) 时序异常检测 (包括 分位数检测 等等) 时间序列滤波 (包括 卡尔曼滤波&#xff0…

【Rd-03E】使用CH340给Rd03_E雷达模块烧录固件

Rd03_E 指导手册 安信可新品雷达模组Rd-03搭配STM32制作简易人体感应雷达灯教程 http://t.csdnimg.cn/mqhkE 测距指导手册网址&#xff1a; https://docs.ai-thinker.com/_media/rd-03e%E7%B2%BE%E5%87%86%E6%B5%8B%E8%B7%9D%E7%94%A8%E6%88%B7%E6%89%8B%E5%86%8C%E4%B8%AD%…

【Android面试八股文】一图展示 Android生命周期:从Activity到Fragment,以及完整的Android Fragment生命周期

图片来源于&#xff1a;https://github.com/xxv/android-lifecycle Android生命周期&#xff1a;从Activity到Fragment 图&#xff1a;android-lifecycle-activity-to-fragments.png 完整的Android Fragment生命周期 图&#xff1a;complete_android_fragment_lifecycle.png…

cve_2022_0543-redis沙盒漏洞复现 vulfocus

1. 原理 该漏洞的存在是因为Debian/Ubuntu中的Lua库是作为动态库提供的。自动填充了一个package变量&#xff0c;该变量又允许访问任意 Lua 功能。 2.复现 我们可以尝试payload&#xff1a; eval local io_l package.loadlib("/usr/lib/x86_64-linux-gnu/liblua5.1.so…

AWT常用组件

AWT中常用组件 前言一、基本组件组件名标签(Label类)Label类的构造方法注意要点 按钮(Button)Button的构造方法注意要点 文本框(TextField)TextField类的构造方法注意要点 文本域&#xff08;TextArea&#xff09;TextArea 的构造方法参数scrollbars的静态常量值 复选框&#x…

文心一言 VS 讯飞星火 VS chatgpt (278)-- 算法导论20.3 5题

五、假设我们创建一个包含 u 1 k u^\frac{1}{k} uk1​ 个簇(而不是全域大小为 x ↓ {\sqrt[↓]{x}} ↓x ​ 的 x ↑ {\sqrt[↑]{x}} ↑x ​ 个簇)的 vEB 树&#xff0c;其每个簇的全域大小为 u 1 − 1 k u ^ {1-\frac{1}{k}} u1−k1​ &#xff0c;其中 k>1 &#xff0c…

【UML用户指南】-13-对高级结构建模-包

目录 1、名称 2、元素 3、可见性 4、引入与引出 用包把建模元素安排成可作为一个组来处理的较大组块。可以控制这些元素的可见性&#xff0c;使一些元素在包外是可见的&#xff0c;而另一些元素要隐藏在包内。也可以用包表示系统体系结构的不同视图。 狗窝并不复杂&#x…

数据库管理-第200期 身边的数据库从业者(20240610)

数据库管理200期 2024-06-10 数据库管理-第200期 身边的数据库从业者&#xff08;20240610&#xff09;首席-薛晓刚院长-施嘉伟邦德-王丁丁强哥-徐小强会长-吴洋灿神-熊灿灿所长-严少安探长-张震总结活动预告 数据库管理-第200期 身边的数据库从业者&#xff08;20240610&#…

匈牙利匹配算法

一 什么是匈牙利匹配算法 匈牙利算法是一种解决二分图最大匹配问题的算法。在二分图中&#xff0c;将左边的点称为X集合&#xff0c;将右边的点称为Y集合&#xff0c;我们需要在X集合和Y集合之间建立一个双向边集合&#xff0c;使得所有的边都不相交。如果我们能够找到一个最大…

前端工程化工具系列(十)—— Browserslist:浏览器兼容性配置工具

Browserslist 是一个能够在不同的前端工具间共享目标浏览器的配置&#xff0c;各工具根据该配置进行代码转译等操作。 具体的这些前端工具为&#xff1a;Autoprefixer、Babel、postcss-preset-env、eslint-plugin-compat、stylelint-no-unsupported-browser-features、postcss-…

文件的基础必备知识(初学者入门)

1. 为什么使用文件 2. 什么是文件 3. 二进制文件和文本文件 4. 文件的打开和关闭 1.为什么使用文件 我们写的程序数据是存储在电脑内存中&#xff0c;如果程序退出&#xff0c;内存回收&#xff0c;数据就丢失&#xff0c;等程序再次运行时&#xff0c;上次的数据已经消失。面…

安利一款非常不错浏览器文本翻译插件(效果很不错,值得一试)

官网地址&#xff1a;https://immersivetranslate.com/ “沉浸式翻译”这个词&#xff0c;由我们发明创造。如今&#xff0c;它已然成为“双语对照翻译”的代名词。自2023年上线以来&#xff0c;这款备受赞誉的 AI 双语对照网页翻译扩展&#xff0c;已帮助超过 100 万用户跨越语…

鸿蒙开发必备:《DevEco Studio 系列一:实用功能解析与常用快捷键大全》

系列文章目录 文章目录 系列文章目录前言一、下载与安装小黑板 二、IDE被忽略的实用功能-帮助&#xff08;Help&#xff09;1.Quick Start2. API Reference3.FAQ 三、常用快捷键一、编辑二、查找或替换三、编译与运行四、调试五、其他 前言 DevEco Studio&#xff09;是基于In…

NLP——电影评论情感分析

python-tensorflow2.0 numpy 1.19.1 tensorflow 2.0.0 导入库 数据加载 数据处理 构建模型 训练 评估 预测 1.基于2层dropout神经网络 2.基于LSTM的网络 #导入需要用到的库 import os import tarfile import urllib. request import tensorflow as tf import numpy a…