乐趣区

关于后端:回望2022拒绝间接性努力面试题第一弹

本文参加了 SegmentFault 思否年度征文「一名技术人的 2022」,欢送正在浏览的你也退出。

前言

写这篇文章的时候曾经是年初四,邻近 2023 年的时候就曾经看到了身边的同学陆续收回本人的年度总结,而本人虽是悲喜交集,但却迟迟下不了笔。直到明天才有了这篇删删减减的迟来的 2022 年度总结。

回望 2022

说到 2022 年的关键词——行程码,衰弱码,核酸全员检测,阳了个阳 …

但让我感触最深的是还是“阳”,当敌人圈里满屏晒着本人的“阳过”图时,还有心愿进入决赛圈的我始终心存着所谓“天选之子”的幸运,然而不知为什么,却又想让本人被这个可怕的病毒盯上。当我真正感化上当前,才迷迷糊糊的晓得本人为什么有“想要感化”的想法了————感化过后,本来都是晚上六点半起床开始新的学习打算的我硬是被闹钟叫到了七点半;本来是早晨十点半才完结一天的“常识更新”的安顿也被打乱,不到九点就合上电脑关上手机刷起短视频来 … 就这样,将近一个月没有更新博客。

这种“光明磊落”把本人放进舒服圈,而后竟少了那么多焦虑和负罪感,而我想要本人“阳”的真正目标其实是想要让本人有个能骗过本人的理由去松散。

阳康后,真的发现自己有很长一段时间在间歇性致力,给本人发明“自我打动”的假象————想要考研,但备考打算却是断断续续的实现;想要更新技术博客,但更新一篇文章后,即便有了灵感也没有及时记录下来。偶尔在逛论坛的时候发现一位博主写的年度总结中,就有一个词:间歇性致力。这让我有种被惊醒的感觉,我打开本人的博客主页,发现最新的文章曾经是一个月前,在草稿箱外面还寄存着没有欠缺好的文章以及断断续续的经验总结。

间歇性致力往往比保持带来的短暂高兴容易上瘾,并且本人致力的下限也会越来越低,而后果通常是恶性循环和事倍功半。

瞻望 2023

2022 年发现自己有了间歇性致力,2023 年要让本人在该补充常识能量的时候跳出“舒服圈”。心愿本人可能在新的一年“卯”足干劲,“兔”破艰难。

面试第一弹

学习面试题,总结面试教训也是 2023 年的一个 flag 吧,这篇文章给大家带来的还有本人在学习上遇到的面试问题。

题目形容

对于堆和栈你是如何了解的,最好是用一个简略的程序形容一下。

问题分析

堆和栈的问题能够说是在计算机的学习中很常见的了,特地是在数据结构中,“堆”,“栈”相对是经常出现的字眼,首先咱们来简略回顾一下堆和栈是什么,而后能够从两者的区别分割方面来答复这个问题,并利用一个简略的 c ++ 程序来形容一下:

,是动静分配内存的一种存储模式,随便读取且不便。
能够看成一组数组对象以二叉树的状态散布,运行时动静分配内存,对读取程序无限度。

,是一种只能后进先出读取的线性表,读取程序限制性强。并且仅能在表尾进行插入和删除操作的线性表,遵循后进先出的准则。

问题解答

堆和栈的区别与分割:

是一种 动静 的概念,它的大小是受动态变化的,取决于程序运行的那一刻所计算的数据,其访问速度绝对于栈来说比 较慢 ;堆是在过程中进行的,并且不是独立过程,因而所有的线程都能够对堆进行拜访,从拜访权限上来说堆是 不平安 的。

是一种 动态 概念,它的大小是在编译时由程序员确定好的;比方函数的调用就是在栈上进行的,当一个函数被调用后,外面的权限是无奈被另一个栈拜访的,也就是说不同函数之间的栈数据是无奈共享的,那么在安全性上就要 比堆平安

堆和栈的优缺点

说到这里,堆和栈的优缺点应该也能答出来一二了吧:


长处:堆申请的空间大 ;能够 动静地分配内存大小
毛病:内存透露 。如果因为某种原因程序没有开释,就会造成内存透露,呈现内存节约;比方在 c ++ 中,咱们应用 new 来创立一个对象时,返回的是一个对象指针,这个指针指向本类刚创立的这个对象。在 c ++ 中调配给指针的只有存储指针值的空间,但对象所占用的空间调配在堆上,因而应用 new 来创建对象时,必须应用 delete 来开释内存。
易产生内存碎片。 后面说到了堆的解决效率是比拟低的,因而就会产生很多自定义的内存碎片;
线程不平安。因为堆不是独立过程,在程序运行过程中其余的过程能够对其进拜访。


长处:线程独立 安全性较高 ;栈数据是能够 共享 ;内存能够及时失去回收,内存更好治理。
毛病:栈取得的空间较小 ,存在栈中的数据大小和生存期必须是确定的,数据的固定性也让栈不足灵活性。
栈溢出问题(stack overflow)因为栈的大小是无限的,当呈现部分数组过大或递归调用档次过多,会超出栈的容量;并且栈上的 buffer 是大小固定的,如果指针或者是数组越界的话,就会影响到栈上原有的数据,造成栈溢出问题。

程序形容

这里用到了 c ++ 中的析构函数来简略解释一下堆和栈(当然在理论开发当中堆和栈远比这要简单的多,举个简略的小例子比拟容易懂):

using namespace std;
class A
{
  public:
    A()
  {cout<<"A 的构造函数"  <<endl;}
    ~A()
  {cout<<"A 的析构函数"<<endl;}
};
class B
{
  A *a;// 在 B 中定义一个指针 
  public:
    B()
  {
    cout<<"B 的构造函数"<<endl;
    a=new A;// 指针指向堆区空间,应用 new 生成对象指针时,主动调用本类的构造函数 
  }
    ~B()
  {
    cout<<"B 的析构函数" <<endl;
    delete a;// 应用关键字 new 创立的对象,用 delete 来撤销;应用 delete 删除这个对象时,首先调用本类的析构函数,再开释占用的内存。}
}; 
int main()
{
  B b;// B 的对象 b 定义在栈区,出栈之后主动调用本类的析构函数 
  return 0;
}

运行后果:

如果将“delete a;”正文掉,那么就会呈现内存泄露的状况,而析构函数能够清理类中有指针、并且指向堆区空间的成员, 开释指针指向的堆区空间, 避免内存泄露。

如果咱们要应用内存宏大的数据或者是数据大小不确定的时候能够应用堆;如果数据内存较小的话,咱们能够应用栈。

简略补充:
在 js 的数据类型中,咱们晓得有根本数据类型和援用数据类型,其中
根本数据类型: Number、String、Boolean、Undefined、Null、Symbol(es6 新增的原始数据类型)是存储在 中的,根本数据类型大小固定,占据空间小,被频繁应用。它的赋值形式是深拷贝。
援用数据类型: object、array、function 存在 中。当咱们须要拜访这三种援用类型的值时,首先得从栈中取得该对象的地址指针,而后再从堆内存中获得所需的数据。它的数据类型是浅拷贝。

举个例子:

// 根本数据类型(深拷贝,寄存在栈)var a=10;
var b=a;
console.log(b);// 输入 10
// 援用数据类型(浅拷贝,寄存在堆)var a=Object();// a 的数据类型是 object
var b=a;
b.num="20";// b 的 num 属性增加到堆内存中,实际上 a 和 b 独特指向了一个堆内存对象
console.log(a.num);// 输入 20

总结

首先祝大家 兔年高兴 ,新的一年 越战越勇 。也心愿本人在 2023 年 冲破舒服圈 回绝间歇性致力

退出移动版