美文网首页
2020-09-24 new delete 堆 栈

2020-09-24 new delete 堆 栈

作者: yuerxiaoshui | 来源:发表于2020-09-26 10:13 被阅读0次
    A a(1); // 栈中分配
    A b = A(1); // 栈中分配
    A* c = new A(1); // 堆中分配
    

    第一种与第二种没有区别,都是在进程虚拟地址空间中的栈中分配内存,而第三种使用 new 则在堆中分配内存。
    栈中分配的内存,分配与释放由系统管理;堆中分配的内存,申请与释放由程序员手动管理。

    堆与栈的对比:

    1. 堆和栈最大可分配的内存的大小
    2. 堆和栈的内存管理方式
    3. 堆和栈的分配效率
    1. 一般来说,对一个进程,栈的大小远远小于堆。栈以 M 为单位,堆以 G 为单位。
    2. 栈是系统数据结构,对于进程/线程是唯一的,它的分配与释放由操作系统来维护,不需要开发者来管理。
      在执行函数时,函数内局部变量的存储单元都可以在栈上创建,函数执行结束时,这些存储单元会被自动释放。
      堆上的内存分配,亦称动态内存分配。程序在运行的期间用malloc申请的内存,这部分内存由程序员自己负责管理,其生存期由开发者决定:在何时分配,分配多少,并在何时用free来释放该内存。
    3. 栈是机器系统提供的数据结构,计算机会在底层对栈提供支持:分配专门的寄存器存放栈的地址,压栈出栈都有专门的指令执行,这就决定了栈的效率 比较高。
      堆则是C/C++函数库提供的,它的机制是很复杂的,例如为了分配一块内存,库函数会按照一定的算法在堆内存中搜索可用的足够大小的空间,如果没有足够大小的空间(可能是由于内存碎片太多),就有可能调用系统功能去增加程序数据段的内存空间,这样就有机会 分 到足够大小的内存,然后进行返回。显然,堆的效率比栈要低得多。
    set<A> temp;
    func(temp);
    
    void func(set<A> &a)
    {
      A m();
      A n();
      a.insert(m);
      a.insert(n);
    }
    

    分析:函数中 m,n 为临时变量,函数退出时会销毁。但 a 是 set<A> 引用类型的变量,故会将 m 与 n 的内容复制一份放到 temp 的存储空间。
    若将 & 改为 ,则函数内写为 (a).insert(m); 即可。

    set<A *> temp;
    func(temp);
    
    void func(set<A *> &a)
    {
      A *m = new A();
      A *n = new A();
      a.insert(m);
      a.insert(n);
    }
    

    分析:需要手工 delete temp 中的 m 和 n。

    set<A>  temp;
    func(temp);
    
    void func(set<A> &a)
    {
      A *m = new A();
      A *n = new A();
      a.insert(*m);  // 复制一份 m 的内容
      a.insert(*n);  // 复制一份 n 的内容
      delete m;
      delete n;
    }
    

    相关文章

      网友评论

          本文标题:2020-09-24 new delete 堆 栈

          本文链接:https://www.haomeiwen.com/subject/utqtuktx.html