日本免费高清视频-国产福利视频导航-黄色在线播放国产-天天操天天操天天操天天操|www.shdianci.com

學無先后,達者為師

網站首頁 編程語言 正文

C++內存分布及用法_C 語言

作者:一個熱愛學習的深度渣渣 ? 更新時間: 2021-12-02 編程語言

一、內存基礎

1、內存分布

通過下面一張圖看看C++的內存分布:

在這里插入圖片描述

棧區:由編譯器自動分配與釋放,存放為程序運行時函數分配的局部變量、函數參數;棧內存分配運算內置于處理器的指令集中,效率很高,但是分配內存的容量有限;

堆區:由newmalloc分配的內存塊,釋放由應用程序控制,不需要編譯器釋放;如果程序員沒有對該內存進行釋放,程序結束后系統自動回收,堆的地方比棧大很多;

靜態區:存放的是static的靜態變量和一些全局變量,特點是只讀、大小固定;靜態變量和全局變量的存儲期是一起的,一旦靜態區的內存被分配,要一直等到程序全部結束后才釋放;

2、棧區與堆區的區別

1、分配方式不同:棧區系統分配系統回收;堆區由程序員手動申請,需要求程序員自行回收,如果沒有回收,系統在程序結束后會進行回收,這種情況會造成內存泄漏;

2、生命周期不同:棧區生命周期是系統分配到系統回收,也就是在大括號內;堆區是從申請到釋放;

3、效率不同:主要原因是地址空間是否連續,棧區地址空間是連續的,效率會高一些;堆區地址空間不連續,需要遍歷鏈表才能找到最近的地址,效率會低一些;

4、內存碎片:堆區容易產生內存碎片,棧區不會;

5、生長方向不同:棧區申請空間的地址(表示地址的八個十六進制數)是從大到小的,堆區申請空間地址是從小到大的。棧區是先進后出的原則,類比棧結構的特點;

  • 棧區特點:更好的局部性,對象自動銷毀;
  • 堆區特點:運行期動態擴展,需要顯示釋放;

注意點:申請的空間是在堆區,變量本身是在棧區!

二、內存分配

1、內存分配方式

可操作的內存分配:

  • 靜態存儲區分配:static靜態變量、全局變量;
  • 棧上分配:局部變量;
  • 堆上分配:newmalloc進行內存分配;

不可操作的內存分配:

內核區、代碼區、局部變量的分配也屬于系統分配;

2、new的用法

C++中通常使用newdelete來構造和銷毀對象;

使用new創建對象,返回的是對象的首地址,需要用指針接收:

int *y = new int(2);
std::cout << *y << std::endl;

對象的構建和銷毀分為兩步:分配內存、所分配內存上構造對象(銷毀與之類似);

new的幾種常見形式:

  • new int(2) :構造單一對象、new int[5]:構造數組;
  • nothrow new:標準庫定義,解決內存分配失敗異常的問題;
  • placement new:使用已經創建的內存,跳過分配內存;
  • new auto

3、delete用法

根據分配的是單一對象還是數組,采用相應的方式銷毀;

int *y = new int[3];
delete[] y;

不能delete一個非new返回的內存(也就是棧內存);
delete nullptr是可被允許的;
同一塊內存不能delete多次;

4、new與malloc的區別

??new不需要指定分配多大,malloc使用的時候必須指定大小;new的底層實現就是malloc,兩者都必須釋放內存,不否則容易造成野指針或內存泄漏。需要注意一點,釋放內存后需設置相關指針為空指針;

總結:

  • 屬性:new為關鍵字(編譯器),malloc是庫函數(需引入頭文件);
  • 參數:new無需指定大小,malloc需指定大小;
  • 返回類型:new返回對象指針,malloc返回void*;
  • 對于自定義的類:new會調用構造和析構函數,malloc不會調用構造和析構函數;
  • 分配失敗:new會拋出異常,malloc會返回空;

5、內存泄漏

是指由于疏忽或錯誤造成程序未能釋放掉不再使用的內存的情況,內存泄漏并非指內存在物理上的小時,而是應用程序分配某段內存后,由于設計錯誤,失去該段內存的控制從而造成內存浪費;

可能的原因:

  • 1、申請后未釋放(最常見)
  • 2、void* 指針的釋放
  • 3、new[] 回收時沒有用delete[] ,數組的回收要注意

三、內存拓展

1、內存概念

??計算機重要部件之一,是外存與CPU進行溝通的橋梁。計算機所有程序都是在內存運行的,因此內存的性能對計算機的影響非常大。內存也稱為內存儲器和主存儲器,作用是暫時存放CPU的運算數據,以及與硬盤等外部存儲器交換的數據;

在這里插入圖片描述

尋址空間:保存內存地址的多少,通常我們說的4G內存,就表示計算機能保存2的32次方個地址,也就是能找到這些地址上的二進制信息;

尋址能力:每個地址里能存多少個bit,現在的計算機大多數是16位機器了;

2、虛擬內存

使得系統運行實際的內存空間比想象的大得多,虛擬內存是可以遠大于物理內存的,同時主要為了使程序運行的時候可以不限制于只訪問內存大小,可以通過虛擬內存地址去訪問磁盤空間;

每一個進程虛擬內存都是獨立的,獨立的享有計算機的內存。虛擬內存地址的大小是與地址總線位數相關,物理內存地址的大小是與物理內存條的容量與磁盤容量相關。

四、思考

1、代碼中的b屬于棧區還是堆區?

void fun()
{
 int *b = new int[14];
}

b是在棧區的變量,由于b是一個局部變量,隨著函數域 的結束被釋放,不需要程序員自行釋放,盡管b使用new進行初始化,還是可以認為分配在棧區;

總結:

本次系統的從內存的基礎概念到內存分配進行了講解,內存是我們開發中最重要的一部分,往往邏輯上的錯誤就會造成內存泄漏,導致程序無法運行。或者一些分配內存的方式不夠細心,也會造成冗余內存的使用。在目前的很多嵌入式板子上,針對內存的接口是必備的,往往也都是基于malloc修改;
還有一點需要注意,不管任何機器上運行程序,操作的都是虛擬內存,內部通過頁表定位到對應的物理內存。關于硬件方面的本質,如果做嵌入式端的話需要深入研究。

原文鏈接:https://blog.csdn.net/weixin_40620310/article/details/121754849

欄目分類
最近更新