C++四种智能指针小结

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

C++四种智能指针auto_ptr、scope_ptr、shared_ptr和weak_ptr。其中auto_ptr是C++98标准化引入的;scope_ptr、shared_ptr和weak_ptr是C++11标准化才引入的(当然,早在C++03的TR1中就已经可以使用了)。我们都知道,auto_ptr虽说简单,但使用起来却到处是坑,以至于大家都不提倡使用,因此在C++11中已经明确被废弃了。shared_ptr是引用计数的智能指针,被奉为裸指针的完美替身,因此被广泛使用。也可能正是这个原因,scope_ptr 和 weak_ptr似乎被大家遗忘了(或许还会以为它们纯属多余)。

1. auto_ptr

auto_ptr 是C++98标准库里面一个轻量级的智能指针的实现,存在于头文件 memory中。其就是内部使用一个成员变量,指向一块内存资源(构造函数),并在析构函数中释放内存资源。从而达到RAII的目的。但是,auto_ptr 的拷贝物与被拷贝物之间是非等价的——这正是导致其到处是坑的根源所在。
我们仔细观察 auto_ptr 的源码就会发现 auto_ptr 的拷贝构造函数和拷贝赋值操作符函数所接受的参数类型都是非const 的引用类型(auto_ptr<_Ty>& , 即我们可以且需要修改源对象),而不是我们一般应该使用的const引用类型,查看源码我们会发现:

         auto_ptr(auto_ptr<_Ty>& _Right) _THROW0()
                 : _Myptr(_Right.release())
                 {        // construct by assuming pointer from _Right auto_ptr
                 }

         template<class _Other>
                 auto_ptr<_Ty>& operator=(auto_ptr<_Other>& _Right) _THROW0()
                 {        // assign compatible _Right (assume pointer)
                 reset(_Right.release());
                 return (*this);
                 }

2. scoped_ptr

scoped_ptr 有着与 auto_ptr 类似的特性。scoped_ptr 与 auto_ptr 间最大的区别主要在于对内存资源拥有权的处理。auto_ptr 在拷贝(复制)时会从源 auto_ptr 自动交出拥有权,而 scoped_ptr 则不允许被复制(正是这一限制,使我们对scoped_ptr 的使用变得有信心且容易)。

3、shared_ptr

shared_ptr 被视为裸指针的克星。你可以像使用普通对象一样使用它,且获得与裸指针一样的行为(接口),并可以获得运行时的多态。

4、weak_ptr
weak_ptr 是为配合 shared_ptr 而引入的一种智能指针来协助shared_ptr 工作,它可以从一个 shared_ptr 或另一个 weak_ptr 对象构造,它的构造和析构不会引起引用记数的增加或减少。没有重载*和->但可以使用lock获得一个可用的shared_ptr对象。
weak_ptr 的实现代码可以简化如下:

template<class T> class weak_ptr   
{   
public:   
    weak_ptr();   

    template<class Y> weak_ptr(const shared_ptr<Y> & r);   
    weak_ptr(const weak_ptr & r);   

    ~weak_ptr();   
    weak_ptr & operator=(weak_ptr const & r);   

    long use_count()const;   
    //判断是否过期   
    bool expired()const;   
    //得到一个空的或者被协助的shared_ptr   
    shared_ptr<T> lock()const;   

    void reset();   
    void swap(weak_ptr<T> & b);   
};  

weak_ptr 的一个重要用途是“打破循环引用”,即解决 shared_ptr (引用计数)在循环引用中的“无能”。例如下面的代码:

class parent;   
class children;   

typedef boost::shared_ptr<parent> parent_ptr;   
typedef boost::shared_ptr<children> children_ptr;   

class parent   
{   
public:   
    ~parent() { std::cout <<"destroying parent\n"; }   

public:   
    children_ptr children;   
};   

class children   
{   
public:   
    ~children() { std::cout <<"destroying children\n"; }   

public:   
    parent_ptr parent;   
};   


void test()   
{   
    parent_ptr father(new parent());   
    children_ptr son(new children);   

    father->children = son;   
    son->parent = father;   
}   

void main()   
{   
    std::cout<<"begin test...\n";   
    test();   
    std::cout<<"end test.\n";   
}  

运行该程序可以看到,即使退出了test函数后,由于parent和children对象互相引用,它们的引用计数都是1,不能自动释放,并且此时这两个对象再无法访问到。这就引起了c++中那臭名昭著的内存泄漏。
一般来讲,解除这种循环引用有下面有三种可行的方法:
- 当只剩下最后一个引用的时候需要手动打破循环引用释放对象。
- 当parent的生存期超过children的生存期的时候,children改为使用一个普通指针指向parent。
- 使用弱引用的智能指针打破这种循环引用。
虽然这三种方法都可行,但方法1和方法2都需要程序员手动控制,麻烦且容易出错。我们知道,由于 weak_ptr 不更改引用计数,类似普通指针,因此只要把循环引用的一方使用 weak_ptr ,即可解除循环引用。所以使用 weak_ptr 则可以比较容易的解决这个问题。对于上面的那个例子来说,只要把children的定义改为如下方式,即可解除循环引用。

class children   
{   
public:   
    ~children() { std::cout <<"destroying children\n"; }   

public:   
    boost::weak_ptr<parent> parent;   
};  

值得一提的是, 虽然通过 weak_ptr 指针可以有效的解除循环引用,但这种方式必须在程序员能预见会出现循环引用的情况下才能使用,也可以是说这个仅仅是一种编译期的解决方案,如果程序在运行过程中出现了循环引用,还是会造成内存泄漏的。因此,不要认为只要使用了智能指针便能杜绝内存泄漏。毕竟,对于C++来说,由于没有垃圾回收机制,内存泄漏对每一个程序员来说都是一个非常头痛的问题。

5. 小结

auto_ptr、scope_ptr、shared_ptr 和 weak_ptr 都应该在什么情况使用(怎么选择)?
auto_ptr: 不提倡使用,即任何情况下都不要使用它。
scope_ptr: 在局部作用域(例如函数内部或类内部),且不需要将指针作为参数来传递的情况下使用。scope_ptr的开销较 shared_ptr 小一些。
shared_ptr: 似乎大部分情况下都可以使用它。1)在scope_ptr可以使用的情况如果使用shared_ptr 的话将会带来较大的开销;2)如果需要讲指针作为参数或者函数的返回值传递的话,则只能使用shared_ptr。
weak_ptr :打破循环引用,解除shared_ptr使用的尴尬。

参考文章:http://blog.youkuaiyun.com/lollipop_jin/article/details/8499530

【各种轮子2】基于Icepak的PCB散热仿真比较 随着电子产品的集成度越来越高,PCB板的尺寸越来越小,板级芯片散热的问题越来越成为电子工程师的一个重要挑战。对于板级芯片散热,主要依靠工程师对PCB自身的设计进行优化,同时要兼顾系统的尺寸和成本。本文分别从芯片角度和PCB角度进行建模,芯片模型选用QFN封装,PCB模型采用走线导入模型,探讨了芯片结构,PCB铜厚,PCB叠层厚度对芯片散热的影响。 阅读详情

相关推荐

使用Python下载ECMWF的ERA-5数据

一、注册账号 [官网]https://www.ecmwf.int/ 二、登录后获取下载key https://cds.climate.copernicus.eu/api-how-to 如图右侧红色框中的内容复制保存为TXT文件,并重命名为“.cdsapirc”,注意前面有点,保存在 C:\Users\username\.cdsapirc,(WINDOWS系统),username指当前电脑登录账户。 三、安装cdsapi库 以pycharm为例: 在pycharm中依次打开:File>setting

wise_sun的博客 7705

c++智能指针详解

详细介绍智能指针的基本原理,分析了使用场景,并且列出了容易踩坑的使用方法及规避方法。

漫步者 987

Vensim系统动力学建模实战:从理论到仿真优化【案例详解】

本文详细介绍了Vensim在系统动力学建模中的实战应用,从基础理论到仿真优化全面解析。通过人口增长、供应链库存优化等典型案例,展示如何利用Vensim构建动态模型并进行参数优化,帮助读者掌握系统动力学建模的核心技术与实践技巧。

weixin_29231725的博客 477

C++:智能指针

本文介绍了智能指针的概念和原理,以及C++标准库中的auto_ptr、unique_ptr和shared_ptr三种智能指针,分析了shared_ptr中的循环引用问题,并由shared_ptr的循环引用问题出发点,介绍了weak_ptr。

weixin_43908419的博客 8673

【ros】ROS1的安装和相关使用方法

主要学习ros相关内容

Greary的博客 2379

2023华为od机试C卷【最富裕的小家庭】C语言 实现

在一颗树中,每个节点代表一个家庭成员,节点的数字表示其个人的财富值,一个节点及其直接相连的子节点被定义为个小家庭。现给你一颗树,请计算出最富裕的小家庭的财富和。

MISAYAONE的博客 500

C++智能指针详解

智能指针有多智能?

小白成长之路 1万+

MATLAB基础应用精讲-【强化学习】Actor - Critic 算法(附python代码实现)

这种架构结合了策略梯度方法(Policy - Gradient Methods)和价值函数估计方法(Value Function Estimation Methods)的优点。在强化学习中,智能体(Agent)需要通过与环境(Environment)的交互来学习最优的行为策略,以获得最大的累积奖励(Cumulative Reward)。

qq_36130719的博客 363

【C++11】智能指针

【C++11】智能指针

weixin_60478154的博客 8318

OWASP-ZAP扫描器的使用

目录 OWASP-ZAP 更新 代理 目录扫描 主动扫描(Active Scan) 扫描结果 生成报告 OWASP-ZAP OWASP Zed攻击代理(ZAP)是世界上最受欢迎的免费安全审计工具之一,由数百名国际志愿者积极维护。它可以帮助你在开发和测试应用程序时自动查找Web应用程序中的安全漏洞。 也可以说ZAP是一个中间人代理。它能够获取你对Web应用程序发出的所有请求以...

谢公子的博客 2万+

TensorRT的安装:一步一步教会你如何安装TensorRT

TensorRT(Tensor Runtime)是由NVIDIA开发的一个用于深度学习推理(inference)优化的库,它可以在NVIDIA的GPU上加速神经网络模型的推理过程,从而提高模型的性能和效率。安装完成后,需要将CUDA的安装路径添加到系统环境变量中,以便系统能够找到CUDA的库文件。根据你安装的CUDA版本,将CUDNN的库文件复制到CUDA的安装目录中。要使用TensorRT,首先需要安装NVIDIA的CUDA和cuDNN库,并根据NVIDIA官方文档安装TensorRT。

Science prince的博客 2373

【C++】智能指针详解

今天我们来讲一下c++11中的智能指针。

就爱摆烂 1万+

Python图像处理之光斑分析

光斑是工程中经常出现的图像数据,其特点是目标明确,分布清晰。对光斑图像的分析,主要包括质心定位、目标截取以及半径拟合等。

微小冷的学习笔记 2857

C++11的智能指针小结

(1.1)指针的小介绍 int b = 9; int *a = &b; cout<< "a="<<a << endl; 1 cout<< "*a=" << *a << endl;2 cout<< "&a=" << &a << endl;3 cout<...

weixin_40393500的博客 476

IDEA的使用指南

IDEA基于java的使用手册,可以最快速的上手,在使用中不断的丰富自己的使用技巧.

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

c++中智能指针使用小结

简介 指针是c/c++中重要的概念,也因为指针,难倒了许多人。 举个例子,对于malloc或new出来的内存,是在堆上分配的。那么从该内存分配完成的时刻开始,这块内存就由应用程序来管理了,包括使用和释放。 c程序中很多与内存管理相关的bug,很大的一块就是忘记释放内存导致的内存泄漏,最终导致系统崩溃。可以说,c编程人员在内存管理上耗费了大量的时间和精力。 c中只有指针,没有智能指针的概念。c++...

guotianqing的博客 1100

Camera2Demo

在Camera2 的基础上进行封装,使得Camera2一堆初始化逻辑与Activity分离,降低耦合度,完成预览拍照并保存的操作

C++ 智能指针深入:四种智能指针所有权模型、原理与常见陷阱全景解析

本文深入探讨了C++智能指针的设计原理与工程实践。首先指出裸指针在复杂控制流中难以保证资源释放,提出RAII机制确保资源自动释放。重点分析了智能指针家族(unique_ptr、shared_ptr、weak_ptr)的本质是通过类型系统精确表达资源所有权关系:unique_ptr实现独占所有权,shared_ptr支持共享资源,weak_ptr解决循环引用问题。文章强调智能指针不仅是语法特性,更是对资源生命周期的工程级解决方案,并警示auto_ptr的失败教训。最后总结使用原则:应根据所有权模型选择合适指针

冰冻三尺非一日之寒 1018

VC中sqlite的使用

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

C++智能指针小结

C++ 11新增的智能指针有三个:unique_ptr, shared_ptr, weak_ptr 要包含的头文件 :memory.h unique_ptr:只能有一个指针指向资源; shared_ptr:多个指针可以指向同一个资源; weak_ptr:用于弥补shared_ptr的不足,解决指针成环问题 定义一个指向类型为X的智能指针: unique_ptr&lt;X&g...

Innocent_code的专栏 430

【C++】C++智能指针详解

程序员可以有效地管理内存的分配与释放,减少内存泄漏的风险,并在需要时打破循环引用。掌握智能指针的使用是现代C++编程的基础,这不仅能提升代码的健壮性,还能使代码更加易于维护。C++中的智能指针是现代C++编程中管理动态内存的关键工具。这样,开发者无需手动管理内存的释放,大大降低了出现内存泄漏的风险。被销毁时,才会释放对象的内存。是一种共享所有权的智能指针,可以让多个指针同时指向同一个对象。如何共享对象的所有权,并通过引用计数来管理对象的生命周期。不会影响对象的引用计数,因此它不会阻止对象的销毁。

2403_86785171的博客 998

C++ 智能指针

本文注意讲述了C++中的智能指针,包括auto_ptr、shared_ptr、weak_ptr ... 等

2201_75663820的博客 1147

【C++】C++11 shared_ptr智能指针使用小结

0x00 前言 文章中的文字可能存在语法错误以及标点错误,请谅解; 如果在文章中发现代码错误或其它问题请告知,感谢! 0x01 手动管理内存弊端 在实际C++开发中,我们可能会因为手动管理内存资源管理不当导致程序运行时的突然崩溃或者后台监控发现内存占有量越来越多等问题,具体的内存管理不当原因有以下: ·内存资源在不使用之后没有及时delete释放造成内存泄漏,导致程序占有的内存资源越来越多; ·内存资源已经释放但是指向该块内存的指针没有改变指向成为野指针,并在不知情的条件下继续使用; ·内存资源释放之后再次

C/C++攻城狮 941

【总结】【C++11】智能指针区别及进步小结(待补充)

智能指针的本质 C++11在std::auto_ptr基础上新增了std::shared_ptr、std::weak_ptr智能指针,同时也修复了boot::make_ptr构造参数限制问题(boost::make_shared()不能接受任意多数量的参数来构造对象)。其实智能指针也并没有像它名字听起来那么神奇,它只是用对象去管理了一个资源指针,同时用一个计数器去计算当前指针引用对象的个数;当管...

从底层爬 720

20200427 学习小结C++智能指针

shared_ptr 共享指针 一、初始化 1、默认初始化 shared_ptr<int> ptr;//默认为空指针 2、使用make_shared shared_ptr<int> ptr=make_shared<int>(10); 3、借助内置指针初始化 shared_ptr<int> ptr(new int (10)); 二、智能指针如何自...

weixin_43327696的博客 245

C++智能指针(整理小结)

为什么要用智能指针? 先不说真正的原因,且看有多少大牛推荐要用: 《C++ Coding Standards》第13章:Ensure resource are owned by objects. Use explicit RAII and smart pointers。 《C++ Common Knowledge》第40章:RAII;第42章:Smart Pointers。 《Effec

得思斋 956

C++小结

C++小结 一、构造函数和析构函数 对象的构造从类层次的最根处开始,在每一层中,首先调用基类的构造函数,然后调用成员对象的构造函数。析构则严格按照与构造相反的次序执行,该次序是唯一的,否则编译器将无法自动执行析构过程。 一个有趣的现象是,成员对象初始化的次序完全不受它们在初始化表中次序的影响,只由成员对象在类中声明的次序决定。这是因为类的声明是唯一的,而类的构造函数可以有多个,因此会有多...

大隐隐于野 366

深入理解C++智能指针:分类、使用及多线程安全性

在c++开发中指针是必不可少的。但是使用不当会引发一系列的bug,如常见的空指针释放,指针的重复释放,悬挂指针等等。这些错误会导致卡死程序,甚至会导致更严重的内存泄漏。C++ 的智能指针 shared_ptr 是对原始指针的一种封装。使用 shared_ptr 可以自动管理内存,避免了内存泄漏的问题。shared_ptr 是 C++11 标准引入的,位于头文件<memory>中。

BXA 5586
上一篇: Qt Creator 中的添加“注释段落”的快捷方法
下一篇: Qt 中定义单例对象
e5Max
博客等级 码龄14年 145粉丝 129原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值