堆栈里的悄悄话——智能指针

栈里的对象

"构造完毕,请睁开眼吧!",迷迷糊糊中,听着这个声音,我睁开了眼睛,一位小哥映入眼帘。

“你是谁?我是谁?这又是什么地方?”,我的大脑一片空白。

“你是一个C++对象,这里是栈空间。我是创建你的线程,你先待着,一会儿会用到你,拜~”

“唉,等一下...”,还没等我回过神,小哥已经走远。

环顾四周,这个叫栈的地方,有好多好多的对象,大小不一,不远处还有一个巨无霸对象足足有好几千字节。

“哇!好大一个对象!”,我不禁发出了惊叹。

“一看就是没见过世面的,这才多小的个头,就在那大呼小叫的”,突然传来一个声音。

“谁在说话?”,我四处望去,却没发现动静。

“往哪看呢,没那么远,就在你旁边”,我这才注意到眼皮底下有个小个子在说话。

“你才8个字节的对象,好大的口气!”

“唉,纠正一下,我可不是对象哦,我只是一个指针,我指向的对象那才叫大呢!”

原来这小个子是个指针,顺着他指向的地址望去,果然有一庞然大物,虽不见其全身,估摸着至少也有几MB的大小。

“唉,你指向的对象为何不和我们在一块儿,我看那地方好像不属于栈的地界儿了”。

“说你没见过世面,你还不承认。咱们这栈空间有限,哪里装得下那么多大对象,他们那里叫堆区,一般有身份的对象都放在那边的。那里的对象都是通过new关键字生成的,你们可没这待遇哦,还有...”

“嘘!先别说话,你看线程小哥在干嘛?”,看到之前的小哥去了堆区,我打断了指针小个子的说话。

堆里的对象

只见小哥执行malloc函数在堆区划了一片空间,接着调用构造函数在那片空间上创建了一个对象。

“你刚才不是说那里的对象是new出来的吗,骗人!”

“这你都不知道,这个new = 内存分配 + 构造函数,而内存分配一般默认就是malloc,不懂还一惊一乍的,切~”,被指针小个子怼了回来,我真想找个缝躲起来。

正在我难为情的时候,线程小哥又来到了栈区,在我的头上不远处又创建了一个对象。

“你们好,我是新来的,请多指教!”

“欢迎欢迎,你好,请问你是?”,我第一个上前打招呼。

“咦,你手里怎么握着刚刚那个新对象的地址呢?你也是个指针吗,怎么跟我长得不一样”,小个子指针也凑了上来。

“这位老弟果然好眼力,我也确实是个指针,不过啊,你只是个裸指针,而我是个智能指针!”,新来这小子言语间透露着一股傲娇的味道。

“智能指针?这是个啥?”,小个子指针继续追问。

“哎哟,没想到见多识广的你也有不知道的事嘛!哈哈”,我趁此机会嘲笑了一把小个子。

智能指针

“好吧,那我就自我介绍下,我是一个shared_ptr,人类将我叫做智能指针,我手里握着一个裸指针,弥补了直接使用裸指针带来的烦恼!现在人类可喜欢用我们了。”

“烦恼?什么烦恼?”,小个子指针有点不太服气。

“当然是内存泄漏啦!像你们直接使用new创建出来的对象,程序员们要是忘记写delete释放,那这对象就成为被抛弃的孤儿,就会白白占用堆空间。一个两个还好,要是是在一个频繁执行的函数中发生这种事情,那堆空间就被这些抛弃的对象占满,那后果不堪设想!”,说完,智能指针的嘴角扬起了微笑。

“哦,还没完呢,裸指针还有个毛病就是谁来释放的问题,因为你们裸指针就是一个地址,可以在函数之间四处传递,最后传来传去,到底谁来释放,是不是还有别的函数和线程在使用都搞不清楚了,要是不释放呢,就内存泄漏了,要是别人还在用呢,释放了又会出问题,所以怎么着都很恼火”,说完,智能指针嘴角又上扬了许多。

小个子指针听完有些气馁,停顿一会之后再一次发出了疑问:“那你们是如何解决这个问题的呢?”

“我的内部有一个计数器,初始创建完对象后,把地址告诉了我,计数器值是1,以后每次把我赋值给别的智能指针,或者是函数传参拷贝到另一个shared_ptr,我的计数器值都会+1,表示又多了一个shared_ptr在使用它,相反的如果有一个shared_ptr对象析构了,那计数器值就-1。直到最后谁发现了这个计数器变为0,说明没人在用这个对象了,那就执行delete把它释放掉。看,是不是很聪明呐!”

“唉,我听明白了,原来你shared_ptr自己也是一个对象,利用自己的构造函数和析构函数来对一个计数器进行增加和减少操作来实现对裸指针指向对象的管理,是这样吧?”,我接上了这小子的话茬。

“对,没错,这个叫引用计数!我本身和你一样,也是一个对象哦,咱们这些在栈里的对象,有一个特别大的好处就是不用担心会内存泄漏,也不用担心析构函数不会被调用,编译器在生成指令的时候都已经自动做好了。”

智能指针的帮手

看着我俩打得火热,小个子指针不开心了,“有什么了不起,我能说出一种情况,就让你当场下不来台,哼!”

“哦,你倒是说说看?”

“如果两个对象A和B,A里面有个shared_ptr指向B,B里面有个shared_ptr指向A,也就是互相引用了,这样子,你们两个shared_ptr计数器永远是1,谁也释放不了,怎么样,没辙了吧!哈哈”,小个子一边说一边拍自己大腿,乐得不行。

我还在脑子里冥想这到底是个什么场景,智能指针开始回怼了:“你说的这种情况一早就想到了,在遇到互相引用的时候,我就要请出我的助手weaked_ptr了,它和我功能类似,最大的区别就是它不增加引用计数,只要A和B其中一方把shared_ptr换成weaked_ptr,就能打破你说的循环!”

小个子没料到这智能指针居然还有帮手,一下子语塞,最后实在没办法,憋出了一句:“你是厉害,可是很多现成的模块接口都是裸指针作为参数,要是用你肯定好多不兼容,还得我们裸指针上。”

“唉,此言差矣,既然是智能指针,这点困难都解决不了,哪有脸敢称智能两字?我们重载了->运算符和*运算符,让人类用起我们来和普通指针一样的体验。还提供了get()方法提供原始指针,在遇到你说的情况下也能用得上。怎么样,这下服了吧?唉,你别走啊,真小气~”

原来没等他说完,小个子指针已经灰溜溜的躲开了。

未完待续·······

彩蛋

“不好了,不好了”,小个子指针气喘吁吁的喊着。

“出什么事了?”

“你们看线程老哥在干嘛”

只见线程老哥执行memcpy函数,正在不断覆盖栈空间,智能指针那家伙已经遭殃,马上到我了·······

欲知后事如何,请关注后续精彩......

精彩回顾

路由器里的广告秘密

内核地址空间大冒险2:中断与异常

一个DNS数据包的惊险之旅

DDoS攻击:无限战争

一条SQL注入引出的惊天大案

内核地址空间大冒险:系统调用

闯荡Linux帝国:nginx的创业故事

一个HTTP数据包的奇幻之旅

远去的传说:安全软件群雄混战史

默认浏览器争霸传奇

我是一个流氓软件线程

产品vs程序员:你知道www是怎么来的吗?

比特宇宙-TCP/IP的诞生

我是一个IE浏览器线程

我是一个杀毒软件线程

我是一个explorer的线程

原文地址:https://www.cnblogs.com/xuanyuan/p/12283822.html

时间: 2024-11-06 11:38:55

堆栈里的悄悄话——智能指针的相关文章

Boost智能指针-基础篇

简介 内存管理一直是 C++ 一个比较繁琐的问题,而智能指针却可以很好的解决这个问题,在初始化时就已经预定了删除,排解了后顾之忧.1998年修订的第一版C++标准只提供了一种智能指针:std::auto_ptr(现以废弃),它基本上就像是个普通的指针:通过地址来访问一个动态分配的对象.std::auto_ptr之所以被看作是智能指针,是因为它会在析构的时候调用delete操作符来自动释放所包含的对象.当然这要求在初始化的时候,传给它一个由new操作符返回的对象的地址.既然std::auto_pt

Boost智能指针-基础知识

简单介绍 内存管理一直是 C++ 一个比較繁琐的问题,而智能指针却能够非常好的解决问题,在初始化时就已经预定了删除.排解了后顾之忧.1998年修订的第一版C++标准仅仅提供了一种智能指针:std::auto_ptr(现以废弃),它基本上就像是个普通的指针:通过地址来訪问一个动态分配的对象. std::auto_ptr之所以被看作是智能指针.是由于它会在析构的时候调用delete操作符来自己主动释放所包括的对象. 当然这要求在初始化的时候,传给它一个由new操作符返回的对象的地址.既然std::a

(转)C++11里的智能指针

1. std::auto_ptr有些违背c++编程思想. 已经被"不建议使用了".2. 下文转自:http://blog.csdn.net/lanergaming/article/details/24273419 c#和java中有自动垃圾回收机制,.net运行时和java虚拟机可以管理分配的堆内存,在对象失去引用时自动回收,因此在c#和jva中, 内存管理不是大问题.c++语言没有垃圾回收机制,必须自己去释放分配的堆内存,否则就会内存泄露. 我相信大部分c++开发人员都遇到过内存泄露

c++ 智能指针(转)

智能指针的使用 智能指针是在 <memory> 标头文件中的 std 命名空间中定义的. 它们对 RAII 或"获取资源即初始化"编程惯用法至关重要. 此习惯用法的主要目的是确保资源获取与对象初始化同时发生,从而能够创建该对象的所有资源并在某行代码中准备就绪. 实际上,RAII 的主要原则是为将任何堆分配资源(例如,动态分配内存或系统对象句柄)的所有权提供给其析构函数包含用于删除或释放资源的代码以及任何相关清理代码的堆栈分配对象. 大多数情况下,当初始化原始指针或资源句柄以

C++智能指针简单剖析

导读 最近在补看<C++ Primer Plus>第六版,这的确是本好书,其中关于智能指针的章节解析的非常清晰,一解我以前的多处困惑.C++面试过程中,很多面试官都喜欢问智能指针相关的问题,比如你知道哪些智能指针?shared_ptr的设计原理是什么?如果让你自己设计一个智能指针,你如何完成?等等--.而且在看开源的C++项目时,也能随处看到智能指针的影子.这说明智能指针不仅是面试官爱问的题材,更是非常有实用价值. 下面是我在看智能指针时所做的笔记,希望能够解决你对智能指针的一些困扰. 目录

C++之智能指针20170920

/******************************************************************************************************************/ 一.C++智能指针_自己实现智能指针 1.使用局部变量结合new的方式,防止new导致的内存泄漏 class sp { private: Person *p; public: sp() : p(0) {}//表明sp的构造函数 继承person的无参构造函数 sp(

基于C/S架构的3D对战网络游戏C++框架 _05搭建系统开发环境与Boost智能指针、内存池初步了解

本系列博客主要是以对战游戏为背景介绍3D对战网络游戏常用的开发技术以及C++高级编程技巧,有了这些知识,就可以开发出中小型游戏项目或3D工业仿真项目. 笔者将分为以下三个部分向大家介绍(每日更新): 1.实现基本通信框架,包括对游戏的需求分析.设计及开发环境和通信框架的搭建: 2.实现网络底层操作,包括创建线程池.序列化网络包等: 3.实战演练,实现类似于CS反恐精英的3D对战网络游戏: 技术要点:C++面向对象思想.网络编程.Qt界面开发.Qt控件知识.Boost智能指针.STL算法.STL.

浅谈RAII&智能指针

关于RAII,官方给出的解释是这样的"资源获取就是初始化".听起来貌似不是很懂的哈,其实说的通俗点的话就是它是一种管理资源,避免内存泄漏的一种方法.它可以保证在各种情况下,当你对对象进行使用时先通过构造函数来进行资源的分配和初始化,最后通过析构函数来进行清理,有效的保证了资源的正确分配和释放.(特别是在异常中,因为异常往往会改变代码正确的执行顺序,这就很容易引起资源管理的混乱和内存的泄漏) 其中智能指针就是RAII的一种实现模式,所谓的智能就是它可以自动化的来管理它所指向那份空间的资源

C++——几种简单的智能指针

最简单的智能指针就是将指针封装在类里,同时将该类的复制与赋值禁用,也就是使该类失去值语义. 实现代码如下: 1 #ifndef SMART_PTR_H 2 #define SMART_PTR_H 3 #include <iostream> 4 5 6 template <typename T> 7 class SmartPtr 8 { 9 public: 10 typedef T value_type; 11 typedef T* pointer; 12 typedef T&