4月29日:智能指针和c++内存分布
先来自己复习复习到时候再去看看亮白风格的C八股文我这个顺序也是按照亮白风格的八股文来的同时复习代码需要上次到github这个应该怎么做1. 复习智能指针:1-1 uinque_ptr 指针:先来说说我自己的对这个指针的看法没有拷贝构造函数也没有赋值重载就是没有operator 函数和利用同类的指针来构造它。这个有个好处就是生命的所有权都归自己所有。这个就是为了解决之前c98的auto_ptr;我还想要说说为什么要这么做第一个原因就是为了为了管理自动释放我们知道c中很多的变量(尤其是堆上new出来的空间需要我们来释放),所以我们需要引入这个智能指针来帮助我们释放构造的时候new析构的自动delet.但是auto_ptr解决了这个问题但是没有解决生命所有权归谁比如我也可以拿到这个变量的指针但是你释放了我还拥有再次释放会导致内存泄露(存疑是内存泄露还是悬空指针呢)可以大致的实现一下吗我来尝试一下:templateclassTclassMyUinque_ptr{private:T*_ptr;public:MyUinque_ptr(T*ptr):_ptr(ptr)/*原因是:把外面的指针给进来,至于需不要const T ptr,unique_ptr 拥有的是一个指针地址而不是某个对象的引用。*/{}MyUinque_ptr(constMyUinque_ptrTuptr)delete;MyUinque_ptroperator(constMyUinque_ptrTuptr)delete;Toperator*(){return*_ptr;}T*operator-(){return_ptr;}MyUinque_ptr(MyUinque_ptrTother):_ptr(other._ptr){//这个就是右值拷贝,所有权需要转移才行other._ptrnullptr;}MyUinque_ptroperator(MyUinque_ptrTother){if(other!this){delete_ptr;//要删除原本的资源防止内存泄露_ptrother._ptr;other._ptrnullptr;}}~MyUinque_ptr(){delete_prt;}};可能写的不好但是我这个是这个意思不允许所有权的转换但是僵死值是可以继续去去放所有权的。1-1-1 批错加上回顾亮白是怎么说的错误1 —— 注释措辞“僵死值是可以继续去去放所有权的”原句第44行但是僵死值是可以继续去去放所有权的。修正第一“僵死值应为将死值”xvalue即经过std::move转换后的右值引用所绑定的对象第二去去放多了一个去字。建议改为但将死值xvalue可以通过移动语义来转移所有权。错误2 —— 对 auto_ptr 问题的理解偏差原句第6行再次释放会导致内存泄露(存疑是内存泄露还是悬空指针呢)修正auto_ptr 的核心问题既不是内存泄露也不是单纯的悬空指针。auto_ptr 拷贝时会转移所有权将源指针置空这带来两个风险源指针置空后如果原持有者继续使用会解引用空指针——未定义行为通常是 crash。若两个 auto_ptr 管理同一块内存析构时会对同一地址delete两次——这是双重释放double free同样是未定义行为但不是内存泄露泄露是指分配了但无人释放那一块内存造成了浪费。所以准确说法auto_ptr 的所有权语义不清晰容易导致未定义行为空指针解引用或 double free而非内存泄露。修正后的完整代码templateclassTclassMyUnique_ptr{private:T*_ptr;public:explicitMyUnique_ptr(T*ptr)// 修正拼写 explicit:_ptr(ptr){}MyUnique_ptr(constMyUnique_ptrTuptr)delete;MyUnique_ptroperator(constMyUnique_ptrTuptr)delete;Toperator*(){return*_ptr;}// 修正返回引用T*operator-(){return_ptr;}MyUnique_ptr(MyUnique_ptrTother):_ptr(other._ptr){other._ptrnullptr;}MyUnique_ptroperator(MyUnique_ptrTother){if(other!this)// 修正取地址比较{delete_ptr;_ptrother._ptr;other._ptrnullptr;}return*this;// 修正补上 return}~MyUnique_ptr(){delete_ptr;// 修正_prt → _ptr}};亮白的风格和我讲的差不多但是我的少了很多细节我们接下来说说什么是shared_ptr和weak_ptr:2-1shared_ptr由于这个unique_ptr是不支持拷贝的但是有时候在项目中时常需要传入指针来完成控制或者利用智能指针来帮助我们完成控制这次就引入了共享指针shared_ptr,内部有一个引用计数用它来可以帮助我们完成这项工作。但我们需要拷贝的时候可以正常拷贝但是其实这个指针的引用计数会,如果释放资源不会立马进行delete而是进行对引用计数进行-1,但引用计数 1 的时候再次释放会真的进行delete。我们可以利用unique_ptr来完成对他的构造。我们把这个shared_ptr叫做强关联.2-2weak_ptr这个是为了搭配shared_ptr来使用的似乎是为了给有一些模块提供一个切入的视角但是又不影响shared_ptr的引用计数。我们把这个叫做弱关联.2-3 错误的地方和亮白的详细解释:前面说错了必须要引用计数为0的时候才会真正的delete.weak_ptr的引用场景错误。应该是给某些模块提供一个观察的视角——weak_ptr 可以观察 shared_ptr 管理的对象是否还活着但不影响引用计数也不直接持有对象。最主要的错误没有提到我的失误比如说shared_ptra持有bb又只有a导致他们两个相互持有这个就会导致错误无法正常释放这个也是weak_ptr的主要作用.另一个错误就是没有说weak_ptr不能拷贝weak_ptr。weak_ptr 不像 shared_ptr/unique_ptr它不能直接用*或-访问对象。必须先通过.lock()提升为 shared_ptr如果对象还活着否则返回空 shared_ptr。#位置问题严重程度1第109行“但” → “当”小2第109行引用计数0才 delete不是1大概念错3第109行“进行对…进行” 语病小4第115行“给有一些” 语法不通 “切入的视角” 太模糊中5第115行没提循环引用这个核心场景大漏了重点6缺失没提 weak_ptr 需通过.lock()提升才能用中2.c内存地址空间老样子我先来画图后面再来详细的自己说说好的其实这个图片有很多错误比如说代码段和静态区完全是胡扯这点的确是我的错误。同时内容分层也没有做好。我们下面可以看到ChatGPT自己生成的照片这个是对的我们先来详细的看一下在讲讲用户态内部的划分栈空间在我的理解里面栈空间很小一般存着局部变量很快比如数组吧不是malloc的那种所以一般算法里面也不敢开特别大的数组。他还存放这个函数的栈帧空间和函数返回地址。堆空间碎片比较多但是比较大一般自由度比较高也是new/malloc出来的地方。他是向高地址生长的内存映射区域挤在这栈空间和堆空间之间。他一般是加载动态库或者一些内存映射文件的。bss段和data区域都是存放全局变量和静态变量的地方主要bss是没有初始化或者初始化为0的全局变量和静态变量的而data则是初始化的rodata区域常量通常是像字符串常量或者字面量。具有只读性质代码段存放代码的只读和可执行。