<kbd id="5sdj3"></kbd>
<th id="5sdj3"></th>

  • <dd id="5sdj3"><form id="5sdj3"></form></dd>
    <td id="5sdj3"><form id="5sdj3"><big id="5sdj3"></big></form></td><del id="5sdj3"></del>

  • <dd id="5sdj3"></dd>
    <dfn id="5sdj3"></dfn>
  • <th id="5sdj3"></th>
    <tfoot id="5sdj3"><menuitem id="5sdj3"></menuitem></tfoot>

  • <td id="5sdj3"><form id="5sdj3"><menu id="5sdj3"></menu></form></td>
  • <kbd id="5sdj3"><form id="5sdj3"></form></kbd>

    還有多少人搞不懂堆內(nèi)存和棧內(nèi)存的區(qū)別?

    共 1654字,需瀏覽 4分鐘

     ·

    2022-06-08 00:46

    大家好,我是魚皮。

    今天分享一個(gè)面試中經(jīng)常被問到的知識點(diǎn):堆內(nèi)存和棧內(nèi)存有什么區(qū)別?平時(shí)開發(fā)應(yīng)該使用堆內(nèi)存還是棧內(nèi)存?

    要回答這個(gè)問題,我們首先需要知道什么是堆內(nèi)存,什么是棧內(nèi)存,它們的分配和回收有什么特點(diǎn)??



    先介紹下棧內(nèi)存:


    棧內(nèi)存是為線程留出的臨時(shí)空間,每個(gè)線程都有一個(gè)固定大小的棧空間,而且棧空間存儲的數(shù)據(jù)只能由當(dāng)前線程訪問,所以它是線程安全的。


    ??臻g的分配和回收是由系統(tǒng)來做的,我們不需要手動控制。


    當(dāng)一個(gè)函數(shù)調(diào)用時(shí),系統(tǒng)就會為該函數(shù)的調(diào)用分配??臻g,當(dāng)函數(shù)返回后,系統(tǒng)就會自動回收這塊空間,同理,下次其它函數(shù)調(diào)用和返回,系統(tǒng)還是會自動分配和回收空間。


    那它是怎么分配和回收的呢?


    可以看這兩個(gè)動畫





    棧空間的大小是固定的,它有一個(gè)水位線,標(biāo)識??臻g的分配狀態(tài),水位線里面的表示已經(jīng)分配,然后這個(gè)水位線會根據(jù)函數(shù)調(diào)用和返回的情況自動調(diào)整。


    這里可以看到,??臻g的分配和回收非常簡單,只需要調(diào)整水位線位置就可以了,沒有任何多余操作。




    那堆內(nèi)存呢?


    我們平時(shí)在C語言和C++中使用malloc和new分配的內(nèi)存就是堆內(nèi)存,堆內(nèi)存的一大特點(diǎn)就是大小不固定,可以動態(tài)擴(kuò)容,空間由程序員動態(tài)分配,更加靈活。


    然而,既然有優(yōu)點(diǎn)也必然伴隨著缺點(diǎn)。


    第一個(gè)缺點(diǎn)就是它容易產(chǎn)生內(nèi)存泄露,malloc出來的沒有free,new出來的如果沒有delete,都會產(chǎn)生內(nèi)存泄露,真正項(xiàng)目內(nèi)存泄露產(chǎn)生的情況肯定比這個(gè)復(fù)雜的多。


    第二個(gè)缺點(diǎn),容易產(chǎn)生內(nèi)存碎片,在分配和回收時(shí)需要對很多內(nèi)存碎片進(jìn)行整理,效率較低,具體可以看這個(gè)動畫。



    所以才會有很多自定義的內(nèi)存分配器,但它肯定還是沒有??臻g分配回收速度快。


    第三個(gè)缺點(diǎn),線程不安全,它不像棧內(nèi)存是線程獨(dú)立的,堆內(nèi)存可以被一個(gè)進(jìn)程內(nèi)所有的線程訪問,多線程操作就容易產(chǎn)生問題,很多奇奇怪怪的操作就是這么引起的。




    那什么變量存儲在棧上,什么存儲在堆上呢?普通的A a,這種就是都存儲在棧上,當(dāng)使用new和malloc分配的空間會存儲在堆上,看這個(gè)圖:

    new出來的實(shí)際空間是在堆上分配,然后在棧上開辟一個(gè)指針大小的空間,這個(gè)空間有一個(gè)指針,指向堆上的那塊內(nèi)存,這樣給變量和堆內(nèi)存之間就關(guān)聯(lián)起來了。




    那什么情況下使用棧內(nèi)存,什么情況下使用堆內(nèi)存呢?


    我整理出來了一個(gè)表,貼在這里:



    速度
    空間管理高效,不會產(chǎn)生碎片會產(chǎn)生內(nèi)存碎片
    訪問權(quán)限只能局部變量可以訪問全局變量
    空間大小限制操作系統(tǒng)限制沒有特定的限制
    內(nèi)存分配連續(xù)隨機(jī)分配
    分配和釋放編譯器指令自動管理程序員手動管理
    開銷
    主要問題空間小內(nèi)存碎片
    靈活性固定大小可以resize


    這里可以根據(jù)實(shí)際需求來決定使用哪類內(nèi)存。


    當(dāng)然,其實(shí)也不用關(guān)注那么多,我一般就是大內(nèi)存使用堆,局部變量小內(nèi)存使用棧。


    這里還涉及到很多其它知識點(diǎn),比如進(jìn)程的內(nèi)存空間布局是怎么樣的,??臻g會不會污染、堆內(nèi)存具體是怎么分配和回收的。


    最后是提問環(huán)節(jié),大家可以在評論區(qū)討論一下哈。


    • 當(dāng)定義一個(gè)vector a(100);?a在哪塊內(nèi)存?那100a的空間又在哪里?

    • 當(dāng)定義一個(gè)array a; a在哪塊內(nèi)存,那100個(gè)a的空間又在哪里?




    參考鏈接

    https://stackoverflow.com/questions/79923/what-and-where-are-the-stack-and-heap

    https://www.guru99.com/stack-vs-heap.html

    https://www.geeksforgeeks.org/stack-vs-heap-memory-allocation/

    最后,歡迎加入?魚皮的編程知識星球(點(diǎn)擊了解詳情),和 8200 多名小伙伴們一起交流學(xué)習(xí),向魚皮和大廠同學(xué) 1 對 1 提問、幫你制定學(xué)習(xí)計(jì)劃不迷茫、跟著魚皮直播做項(xiàng)目(往期項(xiàng)目可無限回看)領(lǐng)取魚皮原創(chuàng)編程學(xué)習(xí)/求職資料等。


    往期推薦

    幾個(gè)對程序員的誤解,害人不淺!

    編程導(dǎo)航,火了!

    Gitee 很無奈!

    我的 IP 歸屬地,是咋被挖出來的?

    我造了個(gè)輪子,完整開源!



    瀏覽 25
    點(diǎn)贊
    評論
    收藏
    分享

    手機(jī)掃一掃分享

    分享
    舉報(bào)
    評論
    圖片
    表情
    推薦
    點(diǎn)贊
    評論
    收藏
    分享

    手機(jī)掃一掃分享

    分享
    舉報(bào)

    <kbd id="5sdj3"></kbd>
    <th id="5sdj3"></th>

  • <dd id="5sdj3"><form id="5sdj3"></form></dd>
    <td id="5sdj3"><form id="5sdj3"><big id="5sdj3"></big></form></td><del id="5sdj3"></del>

  • <dd id="5sdj3"></dd>
    <dfn id="5sdj3"></dfn>
  • <th id="5sdj3"></th>
    <tfoot id="5sdj3"><menuitem id="5sdj3"></menuitem></tfoot>

  • <td id="5sdj3"><form id="5sdj3"><menu id="5sdj3"></menu></form></td>
  • <kbd id="5sdj3"><form id="5sdj3"></form></kbd>
    操逼视频欧美国产 | 天天草,人人草 | 天天日天天射天天舔 | 影音先锋成人在线资源 | 蜜臀无码在线 |