C++11智能指针

全面理解-c++11中的智能指针 智能指针是现代 C++ 内存管理的核心工具,通过明确所有权和自动资源释放,显著提升代码安全性和可维护性。原则,确保资源在生命周期结束时被正确释放,避免内存泄漏。:所有权转移语义不明确(通过拷贝构造函数转移所有权),易导致悬空指针。包含两个指针:一个指向对象,一个指向控制块(含引用计数和删除器)。不增加引用计数,但能检测资源是否有效。:唯一拥有资源,不可复制,但可通过。,是编写高质量 C++ 代码的关键。)管理资源,多个指针共享所有权。资源生命周期不确定,需自动管理。管理的资源,不参与所有权管理。 阅读详情

        C++的内存管理一直是c++程序员的一个痛点,c++98中提供了auto_ptr智能指针用于管理堆对象,但其支持的操作有限(不支持多个指针指向同一个对象,不支持管理堆数组),限制了其应用。c++11标准中引入了boost库的shared_ptr和unique_ptr智能指针用于内存管理,大大方便了动态对象的管理。本文谈谈shared_ptr和unique_ptr的使用。

shared_ptr

智能指针的构造函数被声明为explicit,所以,我们不能将一个内置指针隐式转换为一个智能指针,其支持的赋值方式如下:

{
        std::shared_ptr<Object> p(new Object());       //assignment way 1
        shared_ptr<Object> p1 = make_shared<Object>(); //assignment way 2
        Object *pObject = new Object();                //assignment way3, equal way 1
        shared_ptr<Object > p2(pObject);
}

支持的操作:

p.get()        返回p中保存的指针

p.swap(q)      交换p和q中的指针

p.use_count    返回与p共享对象的智能指针数量

p.unique()     若p.use_count 为1,返回true,否则返回false

p=q       赋值操作,要求p和q都是shared_ptr,且所指向的对象能互相转换。此操作会递减p的引用计数,递增q的引用计数,若p的引用计数变为0,则释放其指向的对象,注意:这里不支持原生指针到智能指针的隐式转换。

另外,和一般指针一样,智能指针支持 *, -> 和 . 运算

    可以使用reset函数来将一个新的指针赋予一个shared_ptr,与赋值类似,reset操作会更新引用计数。此操作经常与unique一起使用,来控制多个shared_ptr共享的对象,例子如下:

if(!p.unique())  //改变底层对象前,检查自己是否是当前对象仅有的用户
    p.reset(new string(*p));  //非唯一用户,在改变对象之前分配新的拷贝
*p += newVal;  //此时已经是唯一用户

shared_ptr用法2:

    shared_ptr的缺省行为是当引用计数为0时删除其所指对象,但可以显示指定一个“删除动作”来改变这一行为,这可以通过创建shared_ptr有一种形式为:shared_ptr p(q, d)  来实现,其中d是一个函数或函数对象(或lamda表达式),可以使在释放对象时所完成的动作由delete变成d所指定的动作,具体的场景如互斥量释放,关闭文件句柄等。如:

 

pthread_mutex_t *pMutex = new pthread_mutex_();
pthread_mutex_init(&pMutex,NULL);
{
pthread_mutex_lock(pMutex);
//do something
...

}

 

使用智能指针形式:

pthread_mutex_t *pMutex = new pthread_mutex_();
pthread_mutex_init(&pMutex,NULL);
{
shared_ptr<pthread_mutex_t> mutexPtr(pMutex, pthread_mutex_unlock);
pthread_mutex_lock(mutexPtr.get());
//do something
...
}  //will auto unlock

进一步封装成类使用:

class Lock{
public:
explicit Lock(Mutex*pm): mutexPtr(pm, unlock) //使用unlock代替delete
{
    lock(mutextPtr.get());
}
private:
    std::shared_ptr<Mutex> mutexPtr; //使用shared_ptr代替raw pointer
};

tips:

1、 永远不要用get初始化另一个智能指针或者为另一个智能指针赋值,使用get获取内置指针应注意避免空间重复释放问题

如以下用法会导致悬空指针:

shared_ptr<int> p(new int(42));
int *q = p.get();
{
    shared_ptr<int>(q);
}
int foo = *p;  //p指向的内存已经被释放

2、 不要混用原生指针和智能指针

int *x(new int(42));
process(shared_ptr<int>(x));
int j = *x;

其中,process定义如下:

void process(shared_ptr<int> ptr){} //离开作用域后智能指针指向的对象被销毁

unique_ptr

顾名思义,unique_ptr指向一个给定的对象,具有唯一性,即其的引用计数为1,其也是一种智能指针。但与shared_ptr不同,其赋值方式不支持拷贝赋值(即拷贝构造函数的参数为unique_ptr类型),也不支持”=”赋值,其正确的赋值方式如下:

unique_ptr<T>p1(newT(...));  //其中T表示泛型

或

unique_ptr<T,D>u(new T(...));  //同shared_ptr,用D代替delete操作

    虽然不能通过拷贝或赋值unique_ptr,但可以通过unique_ptr的release或reset操作过度指针所有权(非const)。这两个操作定义如下:

u.release()    u放弃对指针的控制权,返回原生指针,并将u置空

u.reset(q) 如果q不为nullptr,则令u指向这个对象;否则将u置为空

u.reset()      释放u指向的对象      

    应该注意release操作返回了原生指针,但是却不会释放其指向的内存,因此以下语句是错误的:

p2.release();  //p2不会释放内存,造成内存泄漏

unique_ptr的简单使用示例如下:

    unique_ptr<string> p1(new string("p1"));
    cout << "*p1 = " << *p1 << endl;
    unique_ptr<string> p2(p1.release()); //所有权从p1过渡给p2
    cout << "*p2 = " << *p2 << endl;
    unique_ptr<string> p3(new string("p3"));
    p2.reset(p3.release()); //所有权从p3过渡给p2
    cout << "After reset, *p2 = " << *p2 << endl;

输出结果:

*p1= p1

*p2= p1

After reset, *p2 =p3

    不能拷贝unique_ptr的规则有一个例外:我们可以拷贝或赋值一个将要被销毁的unique_ptr,最常见的是从函数返回一个unique_ptr:

    unique_ptr<int> clone(int p)
    {
        return unique_ptr<int>ret(new int(p));
    }

p.s:

支持u = nullptr; 将指针置空;

C++98标准库中包含了一个auto_ptr类,其具有unique_ptr的部分特性,可以理解为unique_ptr是auto_ptr的升级版。auto_ptr不支持在容器中保存,也不能从函数中返回auto_ptr。

weak_ptr

weak_ptr指向一个shared_ptr管理的对象,将一个weak_ptr绑定到shared_ptr不会改变shared_ptr的引用计数,也不控制所指对象生存期,即“weak”的特点。其通过下面方式进行初始化:

Weak_ptr<T>w(sp)     与shared_ptrsp指向相同对象的weak_ptr

w = sp               sp可以是shared_ptr或weak_ptr,赋值后w共享p指向的对象

w.reset()            将w置空,但不影响对象的生存期

w.use_count()        即shared_ptr对应的use_count

w.expired()          若w.use_count为0,则为true;否则为false

w.lock()             如果expired为true,返回一个空的shared_ptr;否则返回一个指向w的对象的shared_ptr

其使用如下:

auto p =make_shared<int>(42);
weak_ptr<int>wp(p);  //wp为弱共享,p的use_count不变

由于weak_ptr指向的对象可能不存在,所以使用时必须调用lock检查其指向的对象是否仍存在。

智能指针与动态数组

使用unique_ptr管理动态数组

C++11标准库提供了一个可以管理new分配的数组的unique_ptr版本。使用方式如下:

unique_ptr<Object[]>spArray(new Object[2]);

类型说明符中的方括号<Object[]>指出spArray指向一个Object数组,当spArray销毁它管理的指针时,会自动使用delete[]。

由于spArray指向一个数组,所以我们不能直接使用”.”和”->”成员运算符。这时,我们可以使用下标运算符[]来访问数组中的元素:

u[i]  返回u在数组中位置i处的对象,其中u指向一个数组

使用shared_ptr管理动态数组

与unique_ptr不同,shared_ptr不支持直接管理动态数组,也不支持[]运算符。如果希望使用shared_ptr来管理动态数组,可以通过指定delete []作为删除器(不指定的话默认使用delete作为删除器):

shared_ptr<Object>sp(newObject[2], [](int *p){delete[] p;});

由于不支持下标运算符[],因此,为了访问元素,必须用get获取一个内置指针,然后通过它来访问数组元素,如下所示:

for(size_ti = 0; i < 2; ++i)
{
    *(sp.get() + i) = i;
}

 

 

 

 

 

 

 

 

 

 

 

 


 

 

 

 

 

 

 

 

 

 

c++11之智能指针(详解) c++11新特性 智能指针 阅读详情

相关推荐

C语言linux线程库pthread的简单使用教程

POSIX线程(pthread)库POSIX线程库是用于C/C++的基于标准的线程API。

m0_60352504的博客 2077

【C++】智能指针详解

参考资料:《C++ Primer中文版 第五版》 我们知道除了静态内存和栈内存外,每个程序还有一个内存池,这部分内存被称为自由空间或者堆。程序用堆来存储动态分配的对象即那些在程序运行时分配的对象,当动态对象不再使用时,我们的代码必须显式的销毁它们。 在C++中,动态内存的管理是用一对运算符完成的:new和delete,new:在动态内存中为对象分配一块空间并返回一个指向该对象的指针,delet...

如风逝去 22万+

开关电源环路补偿--开关电源进阶知识补充1

笔记 一 . 做开关电源环路补偿时候为了使得环路更加稳定。 1 .-- > 希望开关电源的相位裕量在45° 以上, 2. – > 希望开关电源的增益裕量在10db 以上 3. – > 希望开关电源增益曲线在过0db 时候以20db /dec 斜率下降(体现1个极点) 4. – > 希望开关电源补偿之后的带宽达到开关频率的是1/5 ~1/10,用以原理开关电源的开关噪音。 左边图示电源瞬态拉载和释放负载的时候输出电压存在明显的振铃,说明这个目前的环路相位裕量(phase m

qq_29776365的博客 1万+

C++智能指针详解(auto_ptr、unique_ptr、shared_ptr)

智能指针的应用场景、智能指针的介绍、智能指针的使用与原理、auto_ptr、unique_ptr、shared_ptr、shared_ptr与线程安全、shared_ptr的循环引用、weak_ptr解决循环引用、智能指针与定制删除器、lock与RAII、内存泄漏

wuqiongjin的博客 2560

别再为Word转PDF表格变形发愁了!Aspose.Words for Java 19.5 保姆级避坑指南

本文详细介绍了使用Aspose.Words for Java 19.5解决Word转PDF时表格变形问题的完整方案。从格式转换原理到实战技巧,涵盖固定表格宽度、禁用自动调整、强制文本换行等核心方法,并提供高级场景应对策略和性能优化建议,帮助开发者高效处理复杂文档转换需求。

weixin_28702105的博客 266

验证码接收平台搭建教程(含源代码)

在很多注册流程中,我们常常需要通过短信验证码验证用户的身份。本教程将手把手教你搭建一个验证码接收平台,用于自动接收并展示来自短信网关或短信转发器的验证码。⚠️ 本教程仅供学习使用,请勿用于任何非法用途!本教程展示了一个简单的验证码接收平台的搭建流程,从后端到前端完整实现。你可以将其用于学习 Web 开发、数据库操作以及 Flask 项目部署。访问我的优快云主页。

weixin_52548902的博客 4083

C++11新特性——智能指针之shared_ptr

C++11

m0_67168421的博客 2168

[官方培训]22-UE资产优化 Epic 肖月 笔记

Nanite+Lumen目标:面向TA,美术,不影响视觉的前提下,优化运行和编辑效率引擎:UE5.1延迟管线平台:主流PC,Windows 10 with DX12。

Tcohneyn的博客 1574

shared_ptr简介以及常见问题

本文中的shared_ptr以vs2010中的std::tr1::shared_ptr作为研究对象。可能和boost中的有些许差异,特此说明。 基本功能 shared_ptr提供了一个管理内存的简单有效的方法。shared_ptr能在以下方面给开发提供便利: 1、 使用shared_ptr能有效的解决忘记释放内存带来的内存泄漏问题。同时通过自定义删除器功能还能广泛的用于任

4911

2.6 SST的核心性能指标体系

本文构建了固态变压器(SST)的核心性能指标体系,涵盖电气性能、可靠性、经济性和环境适配性四大类指标。电气性能指标包括运行效率(≥97%)、功率密度(≥900kVA/m³)、谐波畸变率(≤3%)等关键参数;可靠性指标设定MTBF≥43800h、年均故障率≤1.2次/年等标准;经济性指标对比分析了初始购置成本(45-55万元)和全生命周期成本(48-55万元);环境适配性指标则明确了温度、海拔等工况要求。该体系采用量化公式和国标限值,为SST的性能测试、选型和优化提供了统一标准。

技术工作者 599

uniapp - 解决App端报错reportJSException >>>> exception function:createInstanceContext, exception:white sc

uni-app,安卓Android,苹果ios,安卓app端,苹果App端,uniapp苹果安卓app,uniApp报错,reportJSException>>>>exceptionfunction:createInstanceContext,exception:whitescreencausecreateinstanceContextfailed,运行自定义基座时白屏,uniapp项目运行白屏reportJSException,检查没问题依旧报错,第三方库插件,组件,uniapp打包调试

🏆 前端领域优质创作者 1万+

【C++11】智能指针

早期在C语言中我们学习了指针,这个指针学起来真是一个头两个大,当然学习到了这里想必大家对指针就不在害怕了,为了填上C++的不足在C++11中就扩展了智能指针,难道智能指针就真的那么智能吗?⭐主体。

AAlykk的博客 1298

【C++实战(62)】从0到1:C++打造TCP网络通信实战指南

本文是 C++ 网络编程实战专栏第 62 篇,聚焦 TCP 客户端与服务端开发。先阐述 TCP 协议特点、核心 API 及阻塞与非阻塞 IO 区别,打牢基础;再详解 TCP 服务端初始化、客户端连接处理与数据收发,以及客户端初始化、异常处理和协议设计;最后通过简易聊天系统实战,介绍线程池应用、协议解析及稳定性测试,助力开发者掌握 TCP 网络编程实操技能。

邓邓子的博客 999

C++进阶——C++11_智能指针

什么是内存泄漏:内存泄漏指因为疏忽或错误造成程序未能释放已经不再使用的内存,一般是忘记释放或者发生异常释放程序未能执行导致的。内存泄漏并不是指内存在物理上的消失,而是应用程序分配某段内存后,因为设计错误,失去了对该段内存的控制,因而造成了内存的浪费。内存泄漏的危害普通程序运行一会就结束了出现内存泄漏问题也不大,进程正常结束,页表的映射关系解除,物理内存也可以释放。长期运行的程序出现内存泄漏影响很大。

博客 | 复习知识点 + 练习 + 最终的领悟 | 全力以赴 1525

最新Anaconda3的安装配置及使用教程(详细过程)

最新Anaconda3安装使用Anaconda下载方式一:官网下载方式二:清华镜像下载(推荐)Anaconda安装 Anaconda是一个开源的Python发行版本,其包含了conda、Python等180多个科学包及其依赖项 Anaconda + Jupyter 基本上已经是大部分机器学习/数据分析等开发者标配的开发环境, 不多介绍,直接进去正题: Anaconda下载 方式一:官网下载 下载地址传送门: 官网首页:https://www.anaconda.com/ 官网下载页:https://www

HowieXue 薛永浩的博客 34万+

jdk-8u144-linux-x64.tar.gz.

该资源为搭建Linux系统Java环境用,资源的后缀为tar.gz格式的压缩包

【C++11】第一弹——智能指针

  在本章中我们会介绍内存泄漏,智能指针出现的原因以及几种常见的智能指针,他们的特性及模拟实现,希望小伙伴们能够从中有所收获!!!

麦麦的博客 1656

RU DOS版、EFI版32bit/64bit BIOS常用工具

DOS版、EFI版的RU工具,可用来查看IO、MEM、PCI、SMBIOS等资源。亲测在EFI SHELL下可用。

C++11 智能指针

智能指针是C++11引入的重要特性,通过自动管理动态内存的生命周期,极大地减少了内存泄漏和资源管理的复杂性。理解并正确使用智能指针,如std::unique_ptr、std::shared_ptr和std::weak_ptr,是现代C++编程的重要技能。通过结合RAII原则和合适的工具,开发人员可以编写出更安全、高效、易维护的代码,从而提高程序的稳定性和可靠性。希望本文对智能指针的深入探讨能够帮助大家更好地掌握这一强大的编程工具。

wxk2227814847的博客 1736

IMSL CNL 7.0.0 (x86-64)Crack

IMSL CNL 7.0.0 (x86-64)Crack intel的算法库破解文件,这是C++版本的破解文件

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

C++11: 智能指针

C++11 auto_ptr, unique_ptr,shared_ptr,weak_ptr智能指针

2301_82256131的博客 1019

【C++】 C++11 智能指针

C++智能指针解析:shared_ptr的原理与应用 本文介绍了C++智能指针的概念,重点分析了shared_ptr的实现原理和使用方法。传统指针管理内存存在泄露风险,C++11引入智能指针简化内存管理。shared_ptr通过引用计数机制实现多指针共享同一内存对象,当最后一个指针销毁时自动释放内存。文章详细讲解了shared_ptr的初始化方式(优先使用make_shared)、引用计数变化、原始指针获取注意事项以及自定义删除器的用法。同时指出了常见使用误区,如避免用原始指针初始化多个shared_ptr

Antonio915的博客 1203

【C++11】智能指针的使用

C++11智能指针的使用,带你领略智能指针浩瀚的世界

有梦想的电信狗 1282

C++11 智能指针:从原理到实现

本文深入探讨了C++11智能指针的实现原理与使用方式。智能指针通过RAII技术自动管理内存资源,有效解决了传统C++手动内存管理的诸多问题。文章重点分析了三种智能指针:unique_ptr实现独占所有权,禁止拷贝但支持移动语义;shared_ptr通过引用计数实现共享所有权;weak_ptr作为弱引用可解决循环引用问题。每种智能指针都配有详细代码示例,展示了创建、操作和资源管理的关键用法。最后还通过简化实现揭示了unique_ptr和shared_ptr的内部工作机制,包括引用计数和自定义删除器的实现细节。

2301_80541270的博客 1445
上一篇: mac 使用Github搭建个人博客
下一篇: mac 下安装redis-py
LinuxG_G
博客等级 码龄15年 58粉丝 176原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值