查看: 117|回复: 0

C++面试:堆和栈的区别

[复制链接]

3

主题

9

帖子

15

积分

新手上路

Rank: 1

积分
15
发表于 2023-4-14 10:32:06 | 显示全部楼层 |阅读模式
15、堆和栈区别


由编译器进⾏管理,在需要时由编译器⾃动分配空间,在不需要时候⾃动回收空间,⼀般保存的是局部变量和函数参数等。
连续的内存空间,在函数调⽤的时候,⾸先⼊栈的主函数的下⼀条可执⾏指令的地址,然后是 函数的各个参数。
⼤多数编译器中,参数是从右向左⼊栈(原因在于采⽤这种顺序,是为了让程序员在使⽤C/C++的“函数参数⻓度可变”这个特性时更方便。如果是从左向右压栈,第⼀个参数(即描述可变参数表各变量类型的那个参数)将被放在栈底,由于可变参的函数第一步就需要解析可变参数表的各参数类型,即第⼀步就需要得到上述参数,因此,将它放在栈底是很不⽅便的。) 本次函数调用结束时,局部变量先出栈,然后是参数,最后是栈顶指针最开始存放的地址,程序由该点继续运⾏,不会产⽣碎⽚。
栈是⾼地址向低地址扩展,栈低⾼地址,空间较⼩。

由程序员管理,需要⼿动 new delete  malloc free 进⾏分配和回收,如果不进⾏回收的话,会造成内存泄漏的问题。
不连续的空间,实际上系统中有⼀个空闲链表,当有程序申请的时候,系统遍历空闲链表找到 第⼀个⼤于等于申请大小的空间分配给程序,⼀般在分配程序的时候,也会空间头部写⼊内存大小,⽅便 delete 回收空间大小。当然如果有剩余的,也会将剩余的插⼊到空闲链表中,这也是产⽣内存碎⽚的原因。
堆是低地址向⾼地址扩展,空间较⼤,较为灵活。
16、函数传递参数的⼏种⽅式

值传递 形参是实参的拷⻉,函数内部对形参的操作并不会影响到外部的实参。
指针传递:也是值传递的⼀种⽅式,形参是指向实参地址的指针,当对形参的指向操作时,就相当于对实参本身进⾏操作。但是在函数内部可以改变指针的指向,不一定就是之前指向的那块地址。
引⽤传递:实际上就是把引⽤对象的地址放在了开辟的栈空间中,函数内部对形参的任何操作 可以直接映射到外部的实参上⾯。
17、 new / delete, malloc / free 区别

都可以⽤来在堆上分配和回收空间。 new /delete 是操作符, malloc/free 是库函数。
执⾏ new 实际上执⾏两个过程: 1.分配未初始化的内存空间(malloc); 2.使⽤对象的构造 函数对空间进⾏初始化;返回空间的⾸地址。如果在第⼀步分配空间中出现问题,则抛出std::bad_alloc 异常,或被某个设定的异常处理函数捕获处理;如果在第⼆步构造对象时出现 异常,则⾃动调⽤ delete 释放内存。
执⾏ delete 实际上也有两个过程: 1. 使⽤析构函数对对象进⾏析构; 2.回收内存空间 (free)。
以上也可以看出 new 和 malloc 的区别, new 得到的是经过初始化的空间,⽽ malloc 得到的 是未初始化的空间。所以 new 是 new ⼀个类型,⽽ malloc 则是malloc ⼀个字节⻓度的空间。 delete 和 free 同理, delete 不仅释放空间还析构对象,delete ⼀个类型,free ⼀个字节⻓度的空间。
为什么有了 malloc/free 还需要 new/delete? 因为对于⾮内部数据类型⽽⾔,光⽤ malloc /free ⽆法满⾜动态对象的要求。对象在创建的同时需要⾃动执⾏构造函数,对象在消亡以前 要⾃动执⾏析构函数。由于 malloc/free 是库函数⽽不是运算符,不在编译器控制权限之内,不能够把执⾏的构造函数和析构函数的任务强加于 malloc/free,所以有了 new/delete 操作符。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

快速回复 返回顶部 返回列表