C++动态内存new+delete+shared_ptr+unique_ptr

C++ 动态内存管理详解 本文介绍了C++动态内存管理的基本概念、内存分配、释放、内存泄漏以及智能指针等。动态内存管理是C++编程中的重要技能,程序员需要熟练掌握,以避免内存泄漏等问题。在实际编程中,建议使用智能指针自动管理内存,提高代码的可读性和可维护性。 阅读详情

直接管理内存

C++中,动态内存的管理是通过一对运算符来完成的:new+delete。

  • new在动态内存中为对象分配空间并返回一个指向该对象的指针,可以选择对其进行初始化。

  • delete 接受一个动态对象的指针,销毁该对象,并释放与之关联的内存。

new+delete用法

int *pi=new int;//new创建了一个动态的,未初始化的无名对象,返回指向该对象的指针
int *pi=new int(); //,在类型名后跟一对圆括号即代表初始化了。这例初始化0了
string *ps=new string; //初始化为空的string,因为相当于类类型对象将用默认构造函数进行初始化
string *ps=new string(); 

// 支持构造函数用法
string *ps=new string(5,'a');
int *pi=new int(5);
vector<int> *pv=new vector<int>{0,2,3};

// 可以使用auto让初始化器推断对象类型。此方法由于编译器要用初始化器的类型来推断要分配的类型,只有当括号中仅有一初始化器时才可以使用auto
auto p1= new auto(obj);
// auto p2 = new auto{a,b,c}//错误,括号中只能有的那个初始化器

// 动态分配的const对象
const int *pci=new const int(1024);
const string *pcs = new const string;// 类似于其他const对象,动态分配的const对象必须进行初始化。这里的string是隐式初始化了

// 分配销毁数组
int *pa = new int[3];
delete [] pa;
内存耗尽

抛出bad_alloc异常。

int *p1=new int;//若分配失败则抛异常bad_alloc
int *p2=new (nothrow) int;// 若分配失败,new返回一个空指针。意思是不能抛异常
// bad_alloc和nothrow都定义在头文件new中
delete释放动态内存
delete p;//p必须是指向动态分配的内存

int i,*pi1=&i,pi2=nullptr; 
//delete pi1; //未定义:pi1指向一个局部变量

// 释放一个空指针总是没有错误的

//const的指针也是可以销毁的

通常情况下,编译器不能分辨一个指针指向的是静态还是动态的对象。类似地,编译器也不能分辨一个指针所指向的内存是否已经释放了。所以delete表达式,大多数编译器都会编译通过。尽管是错误的

C++11智能指针shared_ptr 、unique_ptr

为了更容易安全地使用动态内存,C++11标准库提供了两种智能指针类型来管理动态对象。智能指针的行为类似于常规指针,重要的区别是它负责自动释放所指向的对象。新标准库提供的这两种智能指针的区别在于管理底层指针的方式:

  • shared_ptr 允许多个指针指向同一个对象
  • unique_ptr 则独占所指向的对象

标准库还定义了一个名为weak_ptr的伴随类,它是一种弱引用,指向shared_ptr所管理的对象。

这三种类型都定义在memory头文件中。#include<memory>

shared_ptr类

类似vector,智能指针也是模板。

#include <memory>
shared_ptr<string> p1; //可以指向string
shared_ptr<list<int>> p2; //可以指向int的list

智能指针的使用方式与普通指针类似。解引用一个智能指针返回它所指向的对象。

#include <memory>
shared_ptr<string> p1; 
if(p1 && p1->empty)  // 第一个是p1不为空,第二个是检查指向一个空string
    *p1 = "hi"; // 取内容解引用

下表列出了shared_ptr和unique_ptr都支持的操作

// shared_ptr和unique-ptr都支持的操作
shared_ptr<T> sp // 智能指针,可以指向类型为T的对象
unique_ptr<T> up

p // 将p用作一个条件判断,若p指向一个对象,则为true
*p // 解引用p获得它指向的对象
p->mem // 等价于(*p).mem
p.get() //返回p中保存的指针。要小心使用,若只能指针释放了其对象返回的指针所指向的对象也就消失了。所以尽量不要把裸指针取出来
swap(p,q) // 交换p、q中的指针
p.swap(q) 


// 下面是shared_ptr独有的操作
make_shared<T>(args)//返回一个share_ptr,指向一个动态分配的类型为T的对象。使用args初始化此对象
share_ptr<T>p(q)// p是shared_ptr q的拷贝此操作会递增q中的计数器。q中的指针必须能转换为T*(参见4.11.2 I,第143页)
p=q //p和q都是shared_ptr,所保存的指针必须能相互转换。此操作会递减p的引用计数,递増q的引用计数若p的引用计数变为0,则将其管理的原内存释放
p.unique() //若p.use_count()为l,返回true否则返回false
p.use_count() // 返回与p共享对象的智能指针数量可能很慢,主要用于调试
make_shared 函数

最安全的分配和使用动态内存的方法是调用一个名为make_shared的标准库函数。

此函数在动态内存中分配一个对象并初始化它,返回指向此对象的shared_ptr。

#include <memory>  
shared_ptr<int> p3 = make_shared<int>(42);// 指向一个值为42的int 的shared_ptr
shared_ptr<string> p4 = make_shared<string>(10,'9'); //指向一个值为'999..'的string
    //即传入的形式是与string构造函数符合的
shared_ptr<int> p5 = make_shared<int>(); //指向一个值初始化的int,值为0
 // 不传递任何参数,对象就会进行初始化
 
// 也可以用auto接收
auto p6 = maked_ptr<vector<string>>();

shared_ptr的拷贝和赋值
// 拷贝和赋值时,对个shared_ptr都会记录有多少个其他shared_ptr指向相同的对象
auto p = make_shared<int>(42); // p指向的对象只有p一个引用者
auto q(p);  // p和q指向相同对象,此对象有两个引用者
// 我们可以认为每个shared_ptr都有一个关联的计算器,通常称为 引用计数 reference count
// 每当拷贝一个shared_otr,计数器都会递增。例如当用一个shared)ptr初始化另一个shared_ptr。
// 当shared_ptr赋予一个新值或是shared_ptr被销毁(例如一个局部的shared_ptr离开其作用域),计算器就会递减。为0时,自动释放管理的对象
shared_ptr自动销毁所管理的对象

当指向一个对象的最后一个shared_ptr被销毁时,shared_ptr类就会自动销毁此对象。(通过成员函数:析构函数)

shared_ptr在无用之后仍然保留的一种可能情况是,你将shared_ptr存放在一个容器中,随后重排了容器,从而不再需要某些元素。在这种情况下, 你应该确保用erase删除那些不再需要的shared_ptr元素。

之前使用的类中,分配的资源都与对应对象生存期一致。例如每个vector都拥有自己的元素。当拷贝一个vector时,原vector和副本vector中的元素是相互分离的。

vector<string> v1;//空vector
{// 新作用域
    vector<string> v2 ={"a","b","c"};
    v1=v2;
}//v2被销毁,v1还有三个元素,是原来v2的拷贝。
// 即vector存在,其中元素才会存在。vector都不存在了,其中元素肯定就销毁了。

但某些类分配的资源具有与元对象相独立的生存期。一般而言,如果两个对象共享底层的数据,当某个对象被销毁时,我们不能单方面地销毁底层数据

Blob<string> b1;//空Blob
{// 新作用域
	Blob<string> b2 ={"a","b","c"};
    b1=b2;//
}//b2被销毁,但b2中的元素不能销毁。而b1指向最初由b2创建的元素
NXP MCU CAN波特率(位时间)配置详解 1. 概述 本文将会详细讲解如何设置NXP MCU的CAN波特率、位时间、采样点等属性。 波特率即CAN总线传输频率,位时间是波特率的倒数,例如波特率是500K,那么位时间 = 1 / 500000 = 0.000002s = 2000ns。 我们先来看一下S32K144单片机的EB中与CAN总线波特率相关的可配置参数有哪些: ... 阅读详情

相关推荐

解锁Cherry Studio高阶玩法:用MCP实现自动化测试与数据爬取

本文深入探讨了如何利用MCP协议与Cherry Studio结合,实现自动化测试与数据爬取的高阶应用。通过Playwright等工具的MCP集成方案,详细解析了自动化测试流水线构建和智能爬虫系统开发的关键技术,显著提升工程效率和系统适应性。

defi6farmer的博客 274

详解c++动态内存new/delete、智能指针shared_ptr、unique_ptr、weak_ptr

可编程内存基本上可分为以后三个大部分静态存储区、栈区、堆区简介。 传统内存管理new和delete、分配智能指针shared_ptr、unique_ptr、weak_ptr的使用实例,以及他们彼此的联系和区别。 简单介绍Allocate使用。

热爱生活,忠于自己 5637

【LTspice】002 第一个仿真电路

目录 1. 光偶元件的工作原理 2. 过零检测电路的工作原理 3. 以PC817光耦搭建一个过零检测电路 1. 光偶元件的工作原理 光耦合器(optical coupler,英文缩写为OC)亦称光电隔离器或光电耦合器,简称光耦。它是以光为媒介来传输电信号的器件。 PC817是一种把红外光发射器件和红外光接受器件以及信号处理电路等封装在同一管座内的器件。当输入电信号加到输入端发光器件LED上,LED发光,光接受器件接受光信号并转换成电信号,然后将电信号直接输出,或者将电信号放大处理成标准数字电平输

m0_59642765的博客 8022

c++11智能指针(二):shared_ptr和自定义的Deleter

本节讨论怎样使用 std::shared_ptr自定义Deleter.当一个shared_ptr对象超出作用域时,其析构函数被调用,在析构函数中,将其引用计数减1,如果引用计数的值变为0,则删除关联的原始指针。要删除析构函数中的内部原始指针,默认情况下,shared_ptr调用delete()函数,即delete Pointer;但是,我们在析构函数中并不总是要使用delete函数,还可能有其他的...

小麒麟的成长之路 1万+

HC32 CAN通信

qqa

zhaopenglihui的博客 5430

FPGA开发者必看:Xilinx PCIe IP核BAR地址配置避坑指南(附实例解析)

本文为FPGA开发者提供了Xilinx PCIe IP核中BAR地址配置的详细避坑指南。文章深入解析了32位与64位地址空间的选择逻辑、Pcie to AXI Translation参数的核心作用,并通过实例说明如何正确配置以避免地址映射错乱和数据访问失败。重点探讨了BAR空间类型、大小设定以及地址转换机制,帮助开发者构建清晰可靠的PCIe系统,是调试与优化PCIe设计的关键参考。

weixin_29252171的博客 424

16.3 shared_ptr常用操作、计数与自定义删除器等

shared_ptr常用操作、计数与自定义删除器等

zzyzxb的博客 1681

手把手教你用CH340给正点原子ESP8266烧录固件(附串口调试技巧)

本文详细讲解了使用CH340模块为正点原子ESP8266烧录AT固件的完整流程与关键技巧。核心在于烧录时必须使用3.3V供电,并正确连接GPIO0引脚至GND以进入下载模式。文章涵盖了从硬件接线、软件参数配置到烧录后串口调试验证的全步骤,并提供了常见问题排查方案,帮助开发者一次性成功完成固件烧录。

weixin_29201933的博客 231

C++智能指针 shared_ptr 精简 教程

C++智能指针 shared_ptr 精简 教程

探索C++编程的奥秘,分享深入的技术见解和实践,旨在激发读者创造力与解决问题的思维。 1506

SCI论文Discussion写作:如何用AI工具三步打造审稿人认可的深度逻辑框架

本文针对SCI论文Discussion写作的痛点,提出利用AI工具三步构建深度逻辑框架的方法。首先,使用Claude等工具搭建个性化提纲,解决“浅显病”与“混乱症”;其次,高效整合文献与结果,填充证据;最后,优化逻辑衔接与学术语言,打造审稿人认可的流畅论证。该方法强调研究者主导,AI辅助,显著提升写作效率与深度。

weixin_28235513的博客 233

Modbus 通信协议详解

Modbus是由 Modicon(现为施耐德电气公司的一个品牌)在 1979 年发明的,是全球第一个真正用于工业现场的总线协议。ModBus网络是一个工业通信系统,由带智能终端的可编程序控制器和计算机通过公用线路或局部专用线路连接而成。其系统结构既包括硬件、亦包括软件。它可应用于各种数据采集和过程监控。为更好地普及和推动Modbus在基于以太网上的分布式应用,目前施耐德公司已将Modbus协议的所有权移交给 IDA(,分布式自动化接口)组织,并成立了 Modbus-IDA 组织。

Projectsauron 的博客 7万+

16.2 new/delete探秘、智能指针总述与shared_ptr基础

new/delete探秘、智能指针总述与shared_ptr基础

zzyzxb的博客 508

【LLC快速上手系列】LLC轻载时,死区时间怎么调才对?别再傻傻乱搞了!

死区时间,就是指。如果你死区设得好,就能让开通前 ( V_DS to 0 ),完美实现!

weixin_43199439的博客 1851

【C++】动态内存(一):动态内存与智能指针——shared_ptr类

对 C++ Primer 第五版第十二章第一节的动态内存与智能指针——shared_ptr 类进行阅读、学习和记录。

YGGP的博客 900

霍尼韦尔SoftMaster使用说明

霍尼韦尔SoftMaster使用说明

复分析 阿尔福斯(Ahlfors) 第三版答案 英文

答案分为十章,有部分习题没有答案,全英文复分析阿尔福斯(Ahlfors) 第三版答案

第5章:高级特性5.1 内存管理:动态内存分配(new/delete)、智能指针(unique_ptr、shared_ptr、weak_ptr)

内存管理是C++编程中的关键部分,错误的内存管理可能导致严重的程序问题。传统的方式是使用new和delete手动管理内存,但这容易导致内存泄漏和悬挂指针等问题。为了简化内存管理并提高代码的安全性,C++11引入了智能指针(unique_ptrshared_ptr和weak_ptr智能指针通过自动管理动态分配的对象,减少了手动管理内存的风险。new和delete:用于动态分配和释放内存,但需要手动管理,容易出错。unique_ptr:独占所有权的智能指针,适合单所有者的场景,性能高效。

xiaoheshang_123的博客 681

VC中sqlite的使用

在VC中对sqlite的使用,实现数据库大批数据的快速插入,读取数据库中的数据在ListCtrl中显示

【C++语法进阶】new与delete直接管理动态内存,C++11智能指针管理动态内存的介绍

介绍C++的动态内存,智能指针的管理及应用

小雨的分享斋 1001

lwip-2.0.3

lwip是瑞典计算机科学院(SICS)的Adam Dunkels 开发的一个小型开源的TCP/IP协议栈。实现的重点是在保持TCP协议主要功能的基础上减少对RAM 的占用。

C++编程之动态内存管理

动态内存管理是 C++ 中管理内存资源的重要机制,它允许程序在运行时根据需求分配和释放内存空间。通过正确地管理动态内存,可以提高程序的灵活性和效率,同时避免内存泄漏等问题。指针与引用动态内存分配(new和delete智能指针(等)防止内存泄漏的策略。

K 984

【C++】C++中的动态内存解析

目录结构: contents structure [-] 动态内存和智能指针 使用shared_ptr管理内存 使用new直接管理内存 shared_ptr和new结合使用 unique_ptr weak_ptr 程序异常情况下的资源释放处理 使用智能指针的陷阱 动态数组 new管理动态数组内存 allocator管理动态数组内存 静态内存...

weixin_30519071的博客 109

C++基础与深度解析 | 动态内存管理 | 智能指针

相反,应该优先考虑使用标准库提供的工具和机制,如智能指针和自定义分配器,来满足特殊的内存管理需求。智能指针自动处理对象的生命周期,包括它们的构造、析构和内存释放,从而减少了内存泄漏和其他内存管理错误的风险。析构时,调用shared_ptr的析构函数,会先将引用计数的值减1,然后判断引用计数的值是否为0,如果为0,则调用delete来删除之前分配的内存。当一个动态分配的对象被所有引用它的指针释放后,如果没有适当的销毁和内存释放,该对象所占用的内存就无法被再次利用,从而导致内存泄漏。

zwcslj的博客 1403

c++primer 个人学习总结--动态内存

通过使用shared_ptr,不会影响资源的生命周期,但能避免访问一个不存在的对象。------------------------------------------------------------------------------------------------------------------------------- unique_ptr:一个unique_ptr独享它所管理的对象,因此,unique_ptr没有拷贝构造,也没有拷贝赋值。

a553694212的博客 516

C++ Primer学习总结 第12章 动态内存

1、申请使用shared_ptr int main() { shared_ptr&lt;string&gt; sp;//定义一个智能指针,但是sp现在还没申请空间 string s("123"); // *sp = s; //无效 // cout &lt;&lt; *sp; sp = make_shared&lt;string&gt;(3,'a');//在动态内存中分配...

sgh666666的博客 283

C++ Primer阅读笔记--动态内存和智能指针

(当用一个 shared_ptr 初始化另一个 shared_ptr,或者将其作为参数进行传递以及作为函数的返回值时,都会使关联的计数器递增;weak_ptr 指向由一个 shared_ptr 管理的对象,将一个 weak_ptr 绑定到一个 shared_ptr 不会改变 shared_ptr 的引用计数;get 函数返回一个内置指针,指向智能指针管理的对象,get 用来将指针的访问权限传递给代码,只有确定代码不会 delete 指针的情况下才能使用 get。当 delete 一个指针后,指针变为。

牵一只蜗牛去散步 559

C++的动态内存分配:从对象生命周期到智能管理

摘要: C++的动态内存管理通过new/delete实现对象生命周期的完整控制,在分配内存时自动调用构造函数,释放时调用析构函数。相比C语言的malloc/free,这种机制确保了资源的安全初始化和清理。现代C++进一步引入智能指针(unique_ptr、shared_ptr),利用RAII技术实现内存自动释放,避免手动管理的风险。unique_ptr提供独占所有权,shared_ptr支持共享所有权(通过引用计数),但需注意循环引用问题。正确使用这些机制可显著提升内存安全性和代码健壮性。

bkspiderx的博客 831

第04章 C++语言专题(一.05)动态内存

本文主要包括:通过 new/delete、shared_ptr、unique_ptr 进行单个对象的动态创建和销毁,通过 new/delete、allocator 进行对象数组的动态分配和释放,以及通过智能指针进行动态数组的管理。

三人行,必有我师,其余为同学。老师好,同学好。 169

动态内存与智能指针

若 p.reset(q) 传递了可选的参数内置指针q,会令p指向q,否则会将p置为 p.reset(p.d) 空。make_shared(args) 返回一个shared_ptr,指向一个动态分配的类型为T的对象。shared_ptrp(q) p是shared_ptr q的拷贝;

m0_51918781的博客 664

【C++ Primer】查缺补漏(一)动态内存

本文是笔者回顾复习c++ primer时候对遗忘点的巩固笔记,非详细学习笔记public:StrBlob();// 添加和修改元素//元素访问private:保证Blob的对象b1和b2中任意一个销毁时vector中的元素继续存在。

m0_73389646的博客 1962
上一篇: c++中nullptr
下一篇: faster rcnn解读
hancoder
博客等级 码龄9年 4135粉丝 167原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值