范文健康探索娱乐情感热点
投稿投诉
热点动态
科技财经
情感日志
励志美文
娱乐时尚
游戏搞笑
探索旅游
历史星座
健康养生
美丽育儿
范文作文
教案论文
国学影视

C堆,栈,RAII

  堆 英文名称 heap,在内存管理的语境下,指的是动态分配的内存空间,这个和数据结构的堆是两回事。
  这里的内存,被分配之后需要手动释放,否则会引发内存泄漏。
  那怎么申请一个堆内存空间呢?
  C语言中使用 void* malloc(size_t size)  来申请一块内存空间,size为申请的字节数。 使用 void free(void* ptr)   来手动释放内存。
  C++则使用  new   和  delete   来申请释放内存。
  C++标准里有一个相关概念是自由存储区,英文是free store,特指使用 new 和 delete 来分配和释放内存的区域。 一般而言,这是堆的一个子集。
  为什么有了 malloc, free, C++中还出现了 new, delete 呢?
  实际上 new, delete 的底层实现是 malloc, free;malloc 只是单纯地申请一块内存空间,但是new不一样,C++中包含面向对象的设计,当我们在new一个对象时,C++不仅要向系统申请一块内存,还需要构造这个对象,调用构造函数,而delete时,则需要调用类的析构函数,然后归还内存空间。
  实际上new的操作类似于这样: T* p; void* mem = operator new(sizeof(T));  // 分配内存,其内部调用malloc try {     p = static_cast(mem);  // 类型转换     p->T::T( ... );  // 调用构造函数     return p; } catch ( ... ){     operator delete(p);     throw; }
  如果申请内存成功,并且调用构造函数正常,则对象构造成功,否则释放申请的内存, 抛出  bad_alloc   异常。
  而 delete 的操作类似于这样: p->T::~T();  // 调用析构函数 operator delete(p);  // 释放内存,内部调用 free
  先调用析构函数,再释放内存,如果反过来,先释放内存就没办法调用析构函数了嘛? 是不是?
  栈  英文名称 stack, 在内存管理的语境下,指的是函数调用过程中产生的本地变量和调用数据的区域。 这个栈和数据结构里的栈高度相似,都满足后进先出(last-in-first-out 或 LIFO)。
  我们先来看一段示例代码,来说明 C++ 里函数调用、本地变量是如何使用栈的。当然,这一过程取决于计算机的实际架构,具体细节可能有所不同,但原理上都是相通的,都会使用一个后进先出的结构。 void foo(int n) {  } void bar(int n){     int a = n + 1;     foo(a); } int main(){     bar(42); }
  生长方向: 栈是朝着地址减小的方向生长的,而堆是朝着地址增大的方向生长的。
  当函数调用另外一个函数时,会把参数也压入栈里然后把下一行汇编指令的地址压入栈,并跳转到新的函数。 新的函数进入后,首先做一些必须的保存工作,然后会调整栈指针,分配出本地变量所需的空间,随后执行函数中的代码,并在执行完毕之后,根据调用者压入栈的地址,返回到调用者未执行的代码中继续执行。
  本地变量就保存在栈上,当函数执行完成之后,保存本地变量的栈内存就被释放掉了。
  上述例子中本地变量是内置的类型,本地变量不光可以是内置的类型,还可以是复杂的类型,比如说类的对象,这时,如果 函数调用结束之后或者发生异常时 ,编译器会自动调用类的析构函数,这个过程叫做 栈展开(stack unwinding) 。
  例如: class A { public:     A() { cout << "A" << endl; }     ~A() { cout << "~A" << endl; } };  int main() {     try {         A a;         throw "error";     }     catch (const char* s) {         cout << s << endl;     }     return 0; }
  由于函数调用栈的是先进后出的执行过程,在某一个栈空间被弹出时,在它上面后进的空间一定已经被弹出了,不可能出现内存碎片。
  另外, 图中每种颜色都表示某个函数占用的栈空间。 这部分空间有个特定的术语,叫做 栈帧(stack frame) 。
  RAII
  上面讲了堆和栈,堆只要正确的使用 new和 delete 也不会造成内存溢出,但是这是比较难的,各种情况都会有意无意 的 导致内存泄漏。 比如: // 1 A* p = new A; ...             // 这一大段代码抛异常了,delete没有被执行 delete p;// 2,分配和释放不在同一个函数内 A* create_A() {     A* p = new A;     return p; }  void f() {     A* p = create_A();     ...  // 中间代码一长就很可能漏掉     delete p; }// 3. 返回子对象的坑 class A { public:     A() {}     ~A() {} private:     int m_a; };  class B : public A { private:     int m_b; };  A create() {     B b;     return b; }
  create 函数返回父类A的对象,实际上函数内返回的是子类B,编译器不会报错,但是多半是不对的,这种现象称为对象切片,把子类包含的数据成员给切掉了。 正确的我们应该返回 pointer  或 pointer like class  。
  下面引出我们的主角RAII,RAII (Resource Acquisition Is Initialization),字面意思,资源获取即初始化。
  RAII 其实是为了解决上述忘记delete引发的内存泄漏问题而出现的,我们只需要把要返回的内容封装成类的对象成员,而这个类的对象就是一个本地变量,而本地变量是在栈上的,当对象离开它的作用域后将自动调用析构函数,我们只需要在析构函数内释放堆内存空间就可以了。 class A { public:     A(int a = 1) : m_a(a) {}     ~A() {}     int m_a; };  class Wrapper { public:     Wrapper(A* pa = NULL) : ptr(pa) {}     ~Wrapper() {         delete ptr;         cout << "~Wrapper" << endl;     }     A* get() const { return ptr; }  private:     A* ptr; };   Wrapper create() {     return Wrapper(new A); }   int main() {     Wrapper w_ptr = create();     cout << w_ptr.get()->m_a << endl;     return 0; }// 输出 1 "~Wrapper"
  这里只是做一个简单的实例,其实可以把它写成  pointer like class  ,让  w_ptr  更像一个指针。
  总的来说,资源在构造函数内获得,在析构函数内释放,实例对象是在栈上的本地变量。
  RAII通常可以用来: 关闭文件释放互斥锁释放其他的系统资源。
  好了, 堆 ,栈,RAII先说到这里了,如果文章有错误的地方还请给我指出来,大家一起进步嘛。
  如果觉得对你有帮助的话请@程序员杨小哥 点个赞,谢谢!

无惧特斯拉降价!比亚迪汉的制胜法宝以技术赋能安全自比亚迪汉上市以来,一直是车圈网红上市一年销量突破10万辆,7月份又取得了8522辆的好成绩,直接打破了中大型轿车长期被豪华品牌所占据的天花板。为了继续强化新能源汽车领导者地位,近高通公布首个5G无人机平台支持AI技术可拍8K视频日前高通Qualcomm公布了首个支持5G技术的无人机平台FlightRB55G,此外该平台还支持AI技术,最高可拍摄8K视频,或是2亿像素照片。高通FlightRB55G是一个通三十多了还用红米手机,会不会很没面子?经过我的观察,其实三十多岁的用户用千元机还挺多的,这其中就有部分红米用户。至于这面子啥的,那就太玻璃心了,难道面子需要一个手机来撑场子?那这面子也太廉价了,再说都三十多的人了,还这为什么那么多人选择在转转买二手iPhone?跟新机有什么区别?追求最新版的iPhone,我觉得是得看个人需求吧,并不是因为你会省钱,就要求别人都会省钱,是不是这个道理。我之前盲目的追求最新款,可以说那个最新款iPhone是满足了我的虚荣需求,台湾现阶段的经济怎么样,有哪些支柱产业?台湾现阶段的经济可能还不如广东一个省。我2010年去的台湾,当时已经不如大陆繁荣!比较冷清。现在可能更是倒退了!曾经是当年亚洲四小龙的台湾已经落后。以蔡英文现在的大陆政策,建议大陆大家为什么觉得国产手机越来越贵了?看来不止我一个人有这种感觉,国产手机确实越来越贵了。但是,要从客观的角度去看待问题才能得到一个正确的答案,不然经不起推敲!首先我们忽略了通货膨胀如果我们把国产手机换成手机,那作为对iPhone13要出了,曾经的旗舰机iPhone11还值得买吗?我觉得如果不介意是4G手机的话,想买还是可以买的,毕竟也是一部真香旗舰手机嘛,iPhone11也是拥有着A13处理器的手机,所以性能释放,至少接下来三年时间绝对够用,而且我觉得iP如何清洁iPhone底部小孔?这四种方法值得收藏,个个都很简单未来智能手机的发展方向是什么?这个答案五花八门,但全身无孔的真一体机显然是关键之一,这也是为什么各大智能手机厂商为什么竭力发展屏下摄像头技术无线快充技术屏幕发声技术等等。不过就目前仅2288元,鸿蒙OS徕卡四摄IP68,华为顶尖旗舰二手机售价亲民各大手机厂商都非常热衷于运营自己的粉丝群体,因为粉丝的力量真的很强大,也可以大幅提升旗下产品的销量,尤其是华为公司遭遇限制之后,许多花粉的表现真的是令人泪目,他们不仅仅愿意在5G时magic3pro拍照对比两台手机都开了AI,夜景对比,请看我下一篇文章。广角,magic3pro比mate40pro拍摄范围更广,但是颜色有点过艳。1倍,magic3pro比mate40pro颜色还原更准年年说凉,年年排队买的苹果要来了,iPhone13全系价格大预测8月13日,知名科技媒体爆料,苹果方面可能已经在录制发布会。iPhone13,要来了。年年凉的苹果山寨机没落以后,每年都会出现一种声音苹果要凉了。原因很简单,他们认为国产手机已经不
餐厅如何选择购买自动洗碗机?在食堂和餐厅使用自动洗碗机可以提高洗碗的效率,降低洗碗的劳动强度。餐厅如何选择购买自动洗碗机?首先,这取决于洗碗机是如何清洗的。清洗方法与清洗效率和质量有关。在餐具的洗涤方法上,喷餐厅如何选择购买自动洗碗机?在食堂和餐馆使用自动洗碗机可以提高洗碗效率,降低洗碗的劳动强度。餐厅如何选择购买自动洗碗机?首先,这取决于洗碗机的清洁方式。清洗方法关系到清洗效率和质量。在餐具的清洗方法上,喷淋洗学校餐厅如何选择洗碗机?目前很多餐厅学校(大学幼儿园)的食堂娱乐场所的厨房等仍然是人工洗碗,而每天清洗餐具的量是几百甚至几万件。如何根据就餐人数合理选择商用洗碗机,解决招聘难人工成本高资源浪费的问题?n洗超声波清洗机的工作原理全自动超声波清洗机的原理主要是将换能器转换为功率超声波频率源的声能,并将其转换为机械振动,使槽内清洗液通过清洗壁向超声波辐射。由于超声波的辐射,槽内液体中的微气泡在声波的作用下能够餐厅洗碗机的优势在哪?随着互联网的发展,餐饮业的大多数餐具也有标准的洗涤方案。如何有效节约劳动力成本?小编向您介绍了餐厅洗碗机的优点,它有效地替代了大量的劳动力成本!接下来,小编将从五个方面向大家展示商揭盖式洗碗机的工作原理揭盖式洗碗机是普通商用洗碗机中较便宜较为简单的洗碗机。特别适用于小型餐厅酒店酒吧等洗涤量小的服务行业。揭盖式洗碗机的工作原理是,程序控制器内的开关触点按照程序设定的要求依次闭合或断ampampquot我的tempo我做主ampampquot的欧扎克针不戳品牌V计划人和企业的发展都有自己的节奏,掌控好自身的发展不可能跟别人去比节奏,不能跟别人比效果。欧扎克CMO李高杨以下是采访实录记者欧扎克出圈的原因是什么?李高杨其实所谓出圈,只是因为消费者青3还没播完,爱奇艺又开始筹备青4了?要说最近最火爆的综艺节目,毫无疑问就是抢占了100多个热搜的选秀节目创造营2021和青春有你3。爱奇艺与腾讯视频从一开始的宣发到开播时间,两档节目的明争暗斗明眼人都能看出来。而具体干货!什么是无主商标?无主商标等于闲置商标吗?什么是无主商标?无主商标是指由于企业破产解散关闭或商标人死亡,在主管机关的商标注册簿内仍然存在的注册商标。简而言之,无主商标就是没有商标持有人但仍合法的商标。无主商标有什么特征呢?吉利起诉曹操货的,获赔10。1万元日前,浙江吉利控股集团有限公司与北京搜狐互联网信息服务有限公司等侵害商标权及不正当竞争纠纷一审民事判决书于近日公布,原告为浙江吉利控股集团有限公司,被告为深圳市曹操货的科技有限公司如何注册个人肖像为商标?会被驳回吗?能够作为商标注册的标志,除了文字图形数字等,自己的肖像也可以为商标申请注册。在生活中,我们也能看到很多以肖像注册为商标的,比如老干妈肯德基王守义等都是知名度比较高的肖像商标。而且随