智能指针

【C++】————智能指针 在C++中没有垃圾回收机制,必须自己释放分配的内存,否则就会造成内存泄露。解决这个问题最有效的方法是使用智能指针(smart pointer)。智能指针是存储指向动态分配(堆)对象指针的类,用于生存期的控制,能够确保在离开指针所在作用域时,自动地销毁动态分配的对象,防止内存泄露。智能指针的核心实现技术是引用计数,每使用它一次,内部引用计数加1,每析构一次内部的引用计数减1,减为0时,删除所指向的堆内存。c++中用的最多的是下面三种智能指针。 阅读详情

 Boost中提供的5类智能指针。分别是:

l        scoped_ptr           独占的指针

l        scoped_array       独占的数组

l        shared_ptr            引用计数指针

l        shared_array         引用计数数组

l        weak_ptr             shared_ptr的一个弱指针(不参与引用计数)

l        intrusive_ptr         自定义的引用计数指针

 

scoped_ptr和scoped_array

对于scoped_ptr和scoped_array是不可以拷贝构造和赋值的(拷贝构造函数和operator=都是私有成员)。所以它们不像auto_ptr那样传递指针的拥有权,而是独占拥有权,直至对象的销毁(当scoped_ptr和scropted_array析构的时候,所指向的对象也会被析构)。

构造:

scoped_ptr<int> a(new int);

scoped_ptr<int> b;

scoped_array<int> c(new int[100]);

scoped_array<int> d;

scoped_ptr使用new T或者是NULL来初始化对象。scoped_array使用new T[]或者NULL来初始化对象。

它们的默认构造函数,是使用NULL来初始化。

访问:

scoped_ptr重载了operator*和operator->操作符,而scoped_array重载了operator[]下标运算符。通过这几个操作符来操作它们所指向的对象。它们都可以通过T* get()成员函数得到原始的指针。

例如:

 scoped_array<char> str(newchar[100]);

 strcpy(str.get(),"hello");

 cout<<str[0]<<str[4]<<endl;//输出ho

void reset(T * p = 0)

reset用于重置指针指向的对象,当调用reset的时候scoped_ptr或scoped_array会先删除原来指向的对象(如果不是指向NULL的话)。reset的参数和它们构造函数的要求是一样的,必须是new T(或new T[])或者是NULL。

swap

swap全局函数和swap成员函数,交换两个智能指针指向的对象。例如:

scoped_ptr<int> a(new int);//a指向一个int

scoped_ptr<int> b;//b指向NULL

swap(a,b);//这时,a指向NULL,b指向一个int

bool

scoped_ptr和scoped_array可以隐式的转换为bool类型,当指向NULL的时候返回false,否则返回true。

类型

scoped_ptr<T>和scoped_array<T>中的类型T不能是void类型。

并且scoped_ptr<T>和scoped_ptr<U>不存在类型转换,即使T和U是可以转换的,scoped_ptr<T>和scoped_ptr<const T>也不能转换。

shared_ptr和shared_array

shared_ptr和shared_array是引用计数的智能指针。

下面仅仅介绍shared_ptr的使用。

构造:

对于shared_ptr<T>来说一共有6个构造函数:

shared_ptr(Y * p);

最普通的构造函数,p一定是一个new Y的指针或NULL。注意这里p的类型是Y*,而不是shared_ptr<T>中的T*,所以p一定要存在一个到T*的类型转换。同时shared_ptr会记住p的类型是Y,当p所指向的对象要被析构的时候,shared_ptr会使用正确的析构函数(Y类型的析构函数,而不是T类型的析构函数)。例如:

struct A

{

 A(){cout<<"A construct"<<endl;}

 ~A(){cout<<"A destory"<<endl;}

};

int main()

{

 shared_ptr<void> a(new A);

 return 0;

}

/*

程序输出:

A construct

A destroy

 

这就说明A被正确的析构的,并不因为shared_ptr<void>的void而不能析构A,例如:

voiddel(void *p){delete p;}这就是错的

*/

 

shared_ptr(Y * p,D d);

同上。d是一个仿函数,用来析构p的,例如:

template <class T>

void my_delete(T * p)

{

 delete p;

}

int main()

{

 shared_ptr<void> a(new A,my_delete<A>);

 return 0;

}

 

shared_ptr(shared_ptr<Y> const & r);

拷贝构造函数,注意也存在类型转换哦。

shared_ptr(weak_ptr<Y> const & r);

虽然weak_ptr不参与引用计数,但是shared_ptr会的。

shared_ptr(std::auto_ptr<Y> & r);

这时r就指向NULL了。

 

重置reset:

void reset();

void reset(Y * p);

void reset(Y * p,D d);

 

shared_ptr<T> & perator=(shared_ptr<T> const & r);

shared_ptr<T> & perator=(shared_ptr<Y> const & r);

shared_ptr<T> & perator=(std::auto_ptr<Y> & r);

使原来shared_ptr指向的对象引用计数减一,并指向另一个对象,类似于重新构造,所以它们的参数和构造函数一样。

引用计数成员函数:

long use_count();返回引用计数

bool unique();返回use_count()==1

其它:

bool类型转换,operator==,operator!=,operator<,swap,get,流输出(输出指针地址)

D* get_deleter()得到deleter,用来析构对象的仿函数指针。

类型转换:

shared_ptr<T> static_pointer_cast<T>(shared_ptr<U> const & r);

shared_ptr<T> const_pointer_cast<T>(shared_ptr<U> const & r);

shared_ptr<T> dynamic_pointer_cast<T>(shared_ptr<U> const & r);

以上是类似于c++类型转换的一些函数。由于shared_ptr支持指针的类型转换,所以shared_ptr可以保存void指针,也可以向基类指针的转换。这点,scoped_ptr就不可以!

 

Weak_ptr

weak_ptr是对shared_ptr的一个访问者,weak_ptr不参与shared_ptr的引用计数,也不会删除所指向的对象。同时,当对象被shared_ptr删除后,weak_ptr就是无效的了。

使用weak_ptr,而不使用T*这样的c++指针的原因是:weak_ptr是可以转换成shared_ptr参与引用计数,而T*不可以(只有new T出来的指针才可以构造shared_ptr)。也就是说,weak_ptr虽然不参与引用计数,但是引用计数这套机制还是存在的,当需要转换成shared_ptr的时候就把这套机制传给shared_ptr。否则的话,使用T*构造shared_ptr的话,相当于有两套机制来管理引用计数,那么一个shared_ptr可能指向无效的对象(对象被另一套引用计数机制删除了)。

构造:

weak_ptr();//构造的weak_ptr指向NULL

weak_ptr(weak_ptr const & r);//拷贝构造函数

weak_ptr(weak_ptr<Y> const & r);//类型转换的构造函数

weak_ptr(shared_ptr<Y> const & r);//通过shared_ptr构造,支持类型转换

 

weak_ptr & perator=(weak_ptr const & r);//赋值运算符的重载

weak_ptr & perator=(weak_ptr<Y> const & r);//类型转换

weak_ptr & perator=(shared_ptr<Y> const & r);//。。。

转换成shared_ptr:

shared_ptr<T> lock();//lock成员函数,通过weak_ptr构造shared_ptr

或者可以使用shared_ptr的构造函数。请参考上面shared_ptr的构造函数。

引用计数:

long use_count();//返回引用计数,虽然不参与引用计数,但是察看还是可以的

bool expired();//返回use_count()==0

其它:

void reset();//重置为NULL

swap成员函数,swap全局函数,operator<重载

intrusive_ptr

intrusive_ptr字面上的意思是侵入式指针,其实就是把引用计数的机制留给使用者来定义。比如windows中的COM对象有自己的一套引用计数机制,那么就可以使用intrusive_ptr来管理引用计数,intrusive_ptr会在适当的时候增加和减少引用计数。

使用intrusive_ptr需要自定义以下两个函数:

void intrusive_ptr_add_ref(T * p);//当增加引用计数时,intrusive_ptr调用

void intrusive_ptr_release(T * p);//当减少引用计数时,intrusive_ptr调用

对于intrusive_ptr我就不多说了,请看下面的一个例子吧。

#include<iostream>

#include<boost/intrusive_ptr.hpp>

usingnamespacestd;

usingnamespaceboost;

structMyObj

{

 int* ref_count;//引用计数

 MyObj()

 {

     ref_count=newint(0);

     cout<<"MyObj construct"<<endl;

 }

 ~MyObj()

 {

     cout<<"MyObj destory"<<endl;

 }

};

voidintrusive_ptr_add_ref(MyObj * p)

{

 cout<<"Add Ref"<<endl;

 ++(*(p->ref_count));

}

voidintrusive_ptr_release(MyObj * p)

{

 cout<<"Release"<<endl;

C++智能指针以及我们为什么要使用智能指针 简单介绍两种智能指针,以及说明我们为什么要使用智能指针。 阅读详情

相关推荐

基于ROS2的无人机野生动物巡查系统设计

自主巡检系统是嵌入式人工智能与机器人技术融合的关键应用方向,其核心在于多源感知融合、实时路径规划与端侧智能识别的协同实现。原理上依赖SLAM定位构建环境地图,结合栅格化建模与混合路径算法(如蚁群+BFS)达成全覆盖遍历;技术价值体现在资源受限平台下的确定性响应与时空对齐能力,支撑高鲁棒性野外作业。典型应用场景包括生态监测、禁飞区巡检及小尺度智能安防。本文围绕ROS2 Humble中间件架构、Livox激光雷达与MaixCAM视觉协同、YOLO11n INT8模型端侧部署等关键技术展开,突出嵌入式AI与实时控

weixin_30598047的博客 648

Learning boost 5 -- Smart ptr

Learning boost 5Smart ptrBoost中提供的5类智能指针。分别是:l         scoped_ptr            独占的指针l         scoped_array         独占的数组l         shared_ptr             引用计数指针l         shared_array         

heroboy2000的专栏 9408

mysql数据库中使用存储过程带来的好处和示例(存储过程的概念、定义、作用等详解)

MySQL的存储过程(Stored Procedure)是一组SQL语句集合。用户通过指定的存储过程名和参数来调用并执行它。存储过程可以在数据库中预编译并存储,这样它们可以被多次调用而无需重新编写或解析SQL语句。 存储过程将复杂的SQL逻辑封装在一个可重用的单元中。多次调用存储过程,而不需要重复编写相同的SQL代码。- 通过封装,可以隐藏复杂的SQL逻辑,只向用户或应用程序提供简单的接口。MySQL的存储过程和编程语言中的函数的原理和目标是一致的:封装可重用的代码逻辑并提高代码的可维护性和可重用性。

weixin_70208651的博客 1717

C++常见智能指针

C++常见智能指针

nz189701的博客 513

汇川Easy 301 和MCGS进行Modbus RTU通讯(485)浮点数读取和写入

4DF0001对应寄存器D0,4DF0003对应寄存器D2。注意:要选com2口,com1口是232通讯。

qq_61916672的博客 2900

【S32K】S32K144入门笔记(4) Lin (Lin stack组件) 驱动超声波雷达实例

0. 引言 Lin这块是我一直没弄懂的部分。很多东西一知半解,当时感觉是硬凑了答案出来。 果然过标的时候出了问题,几个小伙伴帮忙一起刷夜也没搞定,好在标还是顺利过了,不然罪过大了。 之前做lin这块一直用的是linStack组件,这部分包含了协议栈部分,需要对lin的协议比较清楚和理解才好配置。 尤其是,图形界面配置完成后会生成一个ldf文件,这个文件很重要,所有的代码都是基于这个文件生成的,但是这个文件我确认没找到什么介绍资料,所以很多配置都是一点一点凑出来的,再实际验证的。 抓住这次写文档的机会,把当时

YoYo的桃子树 1万+

常见的智能指针

三种常用的智能指针

m0_60492395的博客 1596

【WiFi软件开发】IOCTL和Netlink----用户空间和内核空间交互的两种方式

linux开发中通常会涉及用户空间和内核模块的交互。本文介绍了两种典型的用户空间和内核模块通信方式:ioctl和netlink

liuwe1ye的博客 2347

智能指针 smart_ptr

什么是内存泄漏:内存泄漏指因为疏忽或错误造成程序未能释放已经不再使用的内存的情况。内存泄漏并不是指内存在物理上的消失,而是应用程序分配某段内存后,因为设计错误,失去了对该段内存的控制,因而造成了内存的浪费。内存泄漏的危害:长期运行的程序出现内存泄漏,影响很大,如操作系统、后台服务等等,出现内存泄漏会导致响应越来越慢,最终卡死。

qq_68006585的博客 1413

智能座舱通信技术解析:从CAN总线到车载以太网与V2X

在汽车电子与智能网联快速融合的背景下,座舱智能化已不再是简单的屏幕堆砌,而是依赖底层通信技术构建的复杂系统。CAN总线因高可靠性与确定性传输,持续承担车身控制与安全信号的传递;车载以太网则凭借高带宽优势,成为多屏高清视频与OTA升级的核心通道;V2X车路协同技术进一步将座舱与外界的实时信息互联。理解这些技术的分工协作,是掌握智能座舱架构、开展座舱测试与故障排查的关键。本文从实际测试经验出发,梳理不同总线在座舱内部及外部的应用逻辑,结合低成本的实验台架搭建指南,展示从信号采集、网关转发到多媒体流传输的完整链路

weixin_29284657的博客 342

Allegro如何去掉PCB内层未使用的过孔孔环?

在用Allegro进行PCB设计过程中,遇到铺铜铜箔被焊盘大量割断,导致铺铜不完整,这样就会导致铺铜过电流太小,影响板的性能,严重的会导致板工作不稳定,甚至不工作。解决办法:是去掉内层未使用的过孔孔环,增大过铜箔面积。

bhxc809751502的博客 2571

C++学习之“智能指针”

智能指针 【本节目标】 1.为什么需要智能指针 2.智能指针的使用及原理 3.各种版本的智能指针了解及实现 auto_ptr: c++ 98 管理权转移 公司严格禁止使用它 unique_ptr: c++11 简单粗暴的防拷贝 scoped_ptr: boost库 防拷贝 推荐使用 shared_ptr: c++11 共享、引用计数 推荐 (重点) weak_ptr: c++11 解...

现从事游戏开发领域 | 团队项目be_with开发进行中 web方向感兴趣者私 ——We can do all things. 2963

Agent智能体:核心概念与架构——建立系统认知

本文摘要介绍了Agent智能体的核心概念与架构设计。主要内容包括: Agent定义与分类:阐述了Agent作为能够感知环境、决策执行的智能实体,重点分析了现代基于大语言模型(LLM)的Agent架构。 核心模块组成:详细说明了Agent的五大核心模块(感知、规划、记忆、工具和执行)及其交互流程。 UML建模展示:通过类图和序列图,清晰呈现了Agent系统的静态结构和动态执行过程。 项目结构设计:给出了模块化的代码目录结构,为实际开发提供参考框架。

lza_csdn2019的博客 633

【C++11】智能指针深度详解(什么是智能指针?为什么需要智能指针?如何使用智能指针?)

智能指针这个名词听着挺唬人,其实也没啥,无非就是会自动销毁new出来的对象,对于日常使用来说,还是挺方便的,毕竟C/C++可没有隔壁Java的垃圾回收机制GC,得自己清理垃圾,智能指针可以自动完成垃圾清理这个工作

weixin_45031801的博客 7667

IMSL CNL 7.0.0 (x86-64)Crack

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

Devexpress16.2.6破解工具

Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具

【C++】智能指针

C++中的智能指针,重点讨论了其设计思路、使用场景及标准库中的实现。智能指针基于RAII(资源获取即初始化)原则,通过类的生命周期管理资源,确保资源在异常抛出时仍能正确释放,避免内存泄漏。标准库提供了多种智能指针,如auto_ptr(已弃用)、unique_ptr(独占资源)、shared_ptr(共享资源)和weak_ptr(解决循环引用问题)。shared_ptr通过引用计数管理资源,而weak_ptr则用于打破shared_ptr的循环引用,避免内存泄漏。此外,智能指针还支持删除器,允许自定

记录学习与成长 3211

Statistics and Machine Learning Toolbox

Statistics and Machine Learning Toolbox(带书签),MATLAB统计学习工具

【C++11】智能指针

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

AAlykk的博客 1298

SAP B1中文培訓教材_SDK

公司内部培训资料,对开发工具 ,DIAPI, UIAPI,Add-ON有详细解说

Qt 之 智能指针汇总

来源 还有其他一些,做了一些汇总和测试,就不全列了。 文章目录: 一、垂悬指针的问题 二、Qt中的智能指针        1、QPointer        2、QSharedPointer & QWeakPointer        3、QScopedPointer      &n

一个老菜鸟的学习分享 7567

QT中什么时候使用智能指针:智能指针解决了什么

从使用的层面来讲,智能指针其实是对裸指针(普通指针)的类封装,这使得智能指针实质是一个对象,使用感觉就像一个指针。利用RAII(资源获取即初始化)技术来实现智能指针的特性。使用智能指针的目的,最主要的任务就是解决内存泄漏的问题。通过智能指针来执行垃圾回收的任务。智能指针的这种能力赋予了C++语言本身进行内存垃圾清理的实现。通俗的讲,智能指针就是帮你做了你忘记delete操作的工作。

开软古剑楠 4109

C++基础智能指针

独占智能指针会“拥有”它所指向的对象,某一时刻,只能有一个unique_ptr指向给定的对象,当该指针被销毁时,指向的对象也会随之释放。shared_ptr共享他指向的对象,多个共享指针可以指向(关联)相同的对象,在内部采用计数器机制来实现当新的shared_ptr与对象关联时,引用计数器增加1当shared_ptr超出作用域时,引用计数器减1,当引用计数器变为0时,则表示没有任何shared_ptr与对象关联,则释放该对象​class Testpublic://名字。

没有百宝袋的哆啦A梦的博客 2057

rust智能指针

特性引用 (&T 和 &mut T)智能指针(如 Box、Rc)所有权引用没有所有权,只是借用数据智能指针拥有数据的所有权内存管理不负责内存管理负责内存管理,通常有自动销毁机制生命周期有明确的生命周期生命周期取决于智能指针本身数据存储位置引用通常指向栈或堆上的数据智能指针通常分配堆上的内存操作只提供对数据的访问提供更多的操作功能,如引用计数、自动清理等线程安全不保证线程安全一些智能指针(如 Arc)是线程安全的MyBox(x)

喜欢打篮球的普通人 1798

[C++]智能指针用法

智能指针之间不能混用。weak_ptr要和shared_ptr搭配使用,不能单独使用weak_ptr。weak_ptr的lock()使用是要先调用lock()再调用expired()。调用lock()之后use_count+1。

FL1768317420的博客 2020

C++之智能指针

C++智能指针介绍

2302_81120572的博客 875

关于智能指针(更新中)

在Java中,其自带垃圾回收机制,但c++不同。c++必须释放掉分配的内存,否则会造成内存泄露。由此c++11引入了智能指针。

ouyfg的博客 1110

智能指针总结

1.什么是智能指针?智能指针是 C++ 中用于管理动态分配内存的工具,通过封装原始指针并利用 RAII(资源获取即初始化)机制,自动管理对象的生命周期,避免内存泄漏和悬垂指针问题。智能指针是 C++11 引入的现代化特性,定义在 <memory> 头文件中。2.C++为什么要引入智能指针?自动管理内存 避免内存...

qq_35485206的博客 1060
上一篇: 源代码安全检测工具PC_Lint与ITS4实例 zz
下一篇: 全面介绍Windows内存管理机制及C++内存分配实例(一):进程空间 zz
发现心流
博客等级 码龄20年 52粉丝 24原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值