內存管理這一塊

文章目錄

  • 前言
  • 一、C/C++內存分布
  • 二、C語言中動態內存管理方式
  • 三.C++的內存管理方式
    • new/delete操作內置類型
    • new/delete操作自定義類型
  • 四.定位new
  • 總結


前言

在一行一行的代碼之中,不同的數據存放的位置是有所不同的,正是因為這些數據的性質不同,所以才被安排存放在不同的區域
所以,身為預備程序員,要能夠分辨出不同的數據所存放的位置。


以下是本篇文章正文內容,下面案例可供參考

一、C/C++內存分布

我們先來看下面的一段代碼和相關問題

int golbaval = 1;
static int staticGlobalvar = 1;
void test()
{static int staticval = 1;int localvar = 1;int num1[10] = {1,2,3,4};char char2[] = "abcd";const char * pchar3 = "abcd";int * p1 = (int *)malloc(sizeof(int)*4);int * p2 = (int *)calloc(4,sizeof(int));int * p3 = (int *)realloc(p2,sizeof(int)*4);free(p1);free(p3);}

代碼如上,題目如下:
選項A.棧 B.堆 C.數據段(靜態區)D.代碼段(常量區),下面變量分別存放在哪里?
globavar(C)
staticGlobaval(C)
staticval(C)
localvar(A)
num1(A)

——往全局中看,globavarstatGlobaval均是在全局中定義的,所以在全局中定義的,均屬于靜態區
——static修飾的變量不管在哪里定義都位于靜態區,所以在Test函數的staticval也位于靜態區
——locavar與num1都是在局部定義的變量,出了這個Test函數,兩者均會被銷毀,生命周期較短,所以這兩者均屬于

接下來,是一些比較難的。
char2(A)
*char2(A)
pchar3(A)
*pchar3(D)
p1(A)
*p1(B)

我們可以看到,char2是數組名,char2的空間其實是有5個空間,最后一個空間留給了‘\0’,我們都知道,字符串都是位于常量區的,但是char是我們在棧中定義出來的數組名,也是個變量,相當于常量區中的"abcd\0"拷貝了一份給了char2,所以char2是位于中的,*char2也是位于中的,因為是從常量區拷貝一份給了棧上的char2。
pchar3是一個指針,它指向的位置是指向位于常量區的字符串"abcd\0",pchar3是我們在棧中定義的一個指針變量,所以它位于中,*pchar3就是這塊位于常量區的"abcd\0"它位于代碼段(常量區)
p1是我們在棧中定義的一個指針變量,與pchar3性質相同,所以它是位于
上的一個變量,這個指針變量指向的這塊空間是位于上開辟的,所以p1在上,*p1位于堆上。
在這里插入圖片描述

【說明】
1.又叫堆棧-非靜態成員變量/函數參數/返回值等等,棧是向下生長的。
2.用于程序運行時動態的內存分配,一般來說堆是向上身上的,也不排除有例外是向下身上。
3.數據段–存儲全局數據和靜態數據(像我們在全局中定義的變量以及我們使用static關鍵字修飾的變量)
4.代碼段–可執行的代碼/只讀常量
在這里插入圖片描述

二、C語言中動態內存管理方式

之前我們在前面的學習中就已經對動態內存開辟有了一定的了解,現在讓我們回顧一下吧。
1.void* malloc(size_t size)

括號中輸入的是需要向堆申請多少字節的空間,例如我們想向堆中申請5個int類型的空間,也就是20個字節,那么我們可以這樣描述。(int )malloc(5sizeof(int))。

2.void * calloc(size_t n nemb,size_t size)

跟malloc類似,前面的是元素個數,后面是單個元素字節數,同樣我們向堆中申請5個int類型的空間,用calloc是這樣表示的,(int *)calloc(5,sizeof(int))。
注:calloc會將申請的空間全部初始化為0

3.void *realloc(void * prt,size_t size)

①realloc是用來調整之前申請的內存的空間大小,所以待調整的內存必須是之前在堆上分配的空間。
②prt是指向原先內存的指針,size是新內存字節數,返回的是指向新內存的指針,故需要強轉。
③申請失敗會返回NULL,所以需要檢查申請是否成功。

void test()
{int *p2 = (int *)calloc(4,sizeof(int));int *p3 = (int *)realloc(p2,sizeof(int)*10);//這里需要free(p2)嗎?
}

這里是不需要free(p2)的,p2是指向我們calloc申請的空間,p3則是指向我們新內存的空間,以上代碼是對原先的空間進行擴展。

假設申請失敗,則返回空指針。如果申請成功,分為兩種情況。
①直接在原先的空間后面追加需要添加的空間,這種情況下,p2就跟p3相同,所以free(p3)就等同于free(p2)。
②后面的空間不允許你進行擴展,那么編譯器就會向堆上重新申請一塊大的空間(這塊空間的大小與我們擴展后的空間大小一致),然后把舊空間上的數據拷貝到新申請的大空間里,然后釋放舊空間,即此類情況,編譯器會自動幫我們釋放p2。

三.C++的內存管理方式

C語言的內存管理方式在C++上同時適用,但是在一些場景上C語言就顯得有點力不從心,所以C++推出了屬于自己的內存管理方式。通過new以及delete進行操作。

new/delete操作內置類型

void test()
{//申請一塊int類型的空間int * p4 = new int;//申請一塊int類型的空間,并將其初始化為10int * p5 = new int(10);//動態申請10個int類型的空間int * p6 = new int[10];//釋放空間delete p4;delete p5;delete []p6;
}

這里要對應上,你是new就delete,你是new[],就delete[]。不然容易出錯。

new/delete操作自定義類型

class A
{
public:A(int a = 0):_a(a){cout<<"A()"<<endl;}~A(){cout<<"~A()"<<endl;}
}
private:int _a;
int main()
{A * p1 = malloc(sizeof(A));A * p2 = new int(1);free(p1);delete p2;//內置類型幾乎沒有區別int * p3 = (int *)malloc(sizeof(A));int * p4 = new int;free(p3);delete p4;return 0;
}
class Stack
{
public:Stack(int n = 4):_a(new int[n]),_size(0)_capacity(n){cout << "Stack()"<<endl;}~Stack(){free(_a);_size = _capacity = 0;}
private:int _a;size_t _size;size_t _capacity;
}
int main()
{Stack * p1 = (Stack *)malloc(sizeof(A);Stack * p2 = new Stack(10);free(p1);delete p2;
}

直接上結論:new/delete與malloc/free之間的區別是,前者new的過程中會調用構造函數,delete會調用析構,而后者沒有執行此操作。
★new/delete的本質

new和delete相比于malloc/free而言,new會在malloc的基礎上多了一次構造函數,delete會在free清理資源(也就是析構函數)的基礎上,再次釋放對象。這里我畫個圖,以Stack這個類舉例
在這里插入圖片描述

由圖可知,在棧這個類里面,new會先對棧對象的整體大小進行一個計算,開出一個能夠存放棧三個成員變量的空間,然后再調用構造函數對這個對象進行初始化。最后來到了delete,delete先把向堆上申請的空間資源進行一個清理,再對我們這個對象空間給釋放。
簡單講,new就是operator new + 構造,delete就是operator delete + 析構。

new原理:
operator new函數申請空間。
在申請的空間上執行構造函數,完成對象的構造。
delete原理:
在空間上執行析構函數,完成對象中資源的清理工作。
調用operator delete函數釋放對象的空間。
注意:new在創建對象的時候,創建失敗要拋異常。

四.定位new

定位new是一種特殊的new,前面我們已經學過了普通的new,現在跟著我來看看這兩者的區別吧。
簡單一句話,普通new就是創建對象+構造,定位new就只有構造。

int main()
{A * p1 = (A*)malloc(sizeof(A));//這里p1只是指向了這塊空間,還不能算作是關于A的對象,因為它還沒有初始化。new(p1)A;//這一步就是對A的一個構造函數,此處也可傳參參與構造p1->~A();//需手動進行析構清理資源(對象自身管理的資源)free(p1);//釋放對象本身所在的內存塊//下面案例更加具體A * p2 = (A*)operator new(sizeof(A));//operator new參與創建對象本身的空間new(p2)A(10);//這里使用定位new并且傳參對對象進行構造p2->~A();free(p2);
}

在這里插入圖片描述

總結

本文對內存管理進行了一個簡單的講解。new/delete相比于我們之前傳統的內存管理方法要更方便,這里鼓勵大家多使用new/delete進行內存的一個開發。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/922248.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/922248.shtml
英文地址,請注明出處:http://en.pswp.cn/news/922248.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

linux 環境下Docker 安裝

Docker在線安裝 參考 &#xff1a;https://juejin.cn/book/6844733746462064654/section/6844733746545950734#heading-0 Ubuntu 環境下安裝 $ apt-get install apt-transport-https ca-certificates curl software-properties-common $ install -m 0755 -d /etc/apt/keyrin…

Netty從0到1系列之Netty啟動細節分析

文章目錄一、Netty服務器端啟動細節分析1.1 實現一個簡單的http服務器1.2 服務器端啟動細節分析1.3 創建與初始化 NioServerSocketChannel1.3.1 **通過反射工廠創建 Channel**&#xff1a;1.3.2 **初始化 Channel**1.4 注冊到 Boss EventLoopGroup1.4.1 **異步提交注冊任務**1.…

一個海康相機OCR的程序

這是一個極其復雜和龐大的??機器視覺檢測程序??&#xff0c;其核心特點是??多重冗余、條件判斷和流程分支??。它并非一個簡單的線性流程&#xff0c;而是一個為應對各種復雜工業場景&#xff08;如光照變化、產品位置偏移、識別難度高等&#xff09;而設計的??決策網…

深入解析:preload與prefetch的區別及最佳實踐

在前端性能優化領域&#xff0c;資源加載策略直接影響頁面的加載速度和用戶體驗。<link>標簽的preload和prefetch屬性是瀏覽器提供的兩種關鍵資源預加載機制&#xff0c;它們都能提前加載資源&#xff0c;但適用場景和行為邏輯卻大不相同。本文將從定義、觸發時機、優先級…

[論文閱讀] 人工智能 + 軟件工程(漏洞檢測)| 工業場景漏洞檢測新突破:CodeBERT跨領域泛化能力評估與AI-DO工具開發

工業場景漏洞檢測新突破&#xff1a;CodeBERT跨領域泛化能力評估與AI-DO工具開發 論文信息 論文原標題&#xff1a;Cross-Domain Evaluation of Transformer-Based Vulnerability Detection: Open-Source vs. Industrial Data引文格式&#xff08;APA&#xff09;&#xff1a;[…

【層面一】C#語言基礎和核心語法-01(類型系統/面向對象/異常處理)

文章目錄1 類型系統1.1 為什么需要類型&#xff1f;1.2 .NET 類型系統的兩大支柱&#xff1a;CTS 和 CLS1.3 最根本的分類&#xff1a;值類型 vs 引用類型1.4 內置類型 vs. 自定義類型1.5 類型轉換1.6 通用基類&#xff1a;System.Object2 面向對象編程2.1 類和對象2.2 接口和類…

Deepseek構建本地知識庫

一.本地部署Deepseek Ollama 介紹 目前市面上主流的&#xff0c;成本最低的部署本地大模型的方法就是通過 Ollama 了&#xff1a; Ollama 是一個開源的本地大語言模型運行框架&#xff0c;專為在本地機器上便捷部署和運行大型語言模型&#xff08;LLM&#xff09;而設計。 核心…

idea自動編譯,idea不重啟項目,加載修改的內容

idea自動編譯&#xff0c;idea不重啟項目&#xff0c;加載修改的內容

幸運盒項目—測試報告

幸運盒測試報告 目錄幸運盒測試報告一. 概要二. 測試環境三. 測試用例腦圖四. 測試用例1. 功能測試1. 注冊功能2. 密碼登錄功能3. 驗證碼登錄功能4. 注冊用戶功能5. 創建獎品功能6. 新建抽獎活動功能8. 獎品列表9. 活動列表2. 界面測試1. 注冊界面2. 密碼登錄界面3. 驗證碼登錄…

Estimator and Confidence interval

Coefficient of determination and sample correlation coefficient R2SSRSSTR^2 \frac{SSR}{SST}R2SSTSSR? SSR∑i1n((yi^?yˉ)2)SSR\sum_{i1}^n((\hat{y_{i}}-\bar{y})^2)SSR∑i1n?((yi?^??yˉ?)2) SST∑i1n((yi?yˉ)2)SST\sum_{i1}^n((y_{i}-\bar{y})^2)SST∑i1n?…

【網絡編程】TCP 服務器并發編程:多進程、線程池與守護進程實踐

半桔&#xff1a;個人主頁&#x1f525; 個人專欄: 《Linux手冊》《手撕面試算法》《網絡編程》&#x1f516;很多人在喧囂聲中登場&#xff0c;也有少數人在靜默中退出。 -張方宇- 文章目錄前言套接字接口TCP服務器TCP 多進程TCP 線程池重寫Task任務放函數對象客戶端重連進程…

還停留在批處理時代嗎?增量計算架構詳解

在當今的數字化環境中&#xff0c;企業不再只是一味地囤積數據——他們癡迷于盡快把數據轉化為可付諸行動的洞察。真正的優勢來自于實時發現變化并立即做出反應&#xff0c;無論是調整推薦策略還是規避危機。 十年前&#xff0c;硬件與平臺技術的進步讓我們能夠從容應對海量數…

DataSet-深度學習中的常見類

深度學習中Dataset類通用的架構思路 Dataset 類設計的必備部分 1. 初始化 __init__ 配置和路徑管理&#xff1a;保存 config&#xff0c;區分 train/val/test 路徑。加載原始數據&#xff1a;CSV、JSON、Numpy、Parquet 等。預處理器/歸一化器&#xff1a;如 StandardScaler&am…

【VC】 error MSB8041: 此項目需要 MFC 庫

? 目錄 ?&#x1f6eb; 導讀問題背景環境1?? 核心原因&#xff1a;MFC 組件缺失或配置不當2?? 解決方案&#xff1a;安裝 MFC 組件并驗證配置2.1 步驟1&#xff1a;檢查并安裝 MFC 組件2.2 步驟2&#xff1a;檢查并修正項目配置2.3 步驟3&#xff1a;針對特定場景的補充方…

Java零基礎學習Day10——面向對象高級

一.認識final1.含義final關鍵字是最終的意思&#xff0c;可以修飾&#xff1a;類&#xff0c;方法&#xff0c;變量修飾類&#xff1a;該類被稱為最終類&#xff0c;特點是不能被繼承修飾方法&#xff1a;該方法被稱為最終方法&#xff0c;特點是不能被重寫了修飾變量&#xff…

Qt中解析JSON文件

Qt中解析JSON文件 在Qt中解析JSON字符串主要有兩種方式&#xff1a;使用QJsonDocument類或使用QJsonDocument結合QVariant。以下是詳細的解析方法&#xff1a; 使用QJsonDocument&#xff08;推薦&#xff09; 這種方式的主要相關類如下&#xff1a; QJsonDocument: QJsonDocum…

深度解析HTTPS:從加密原理到SSL/TLS的演進之路

在互聯網時代,數據安全已成為不可忽視的基石。當我們在瀏覽器地址欄看到"https://"前綴和那把小小的綠色鎖圖標時,意味著正在進行一場受保護的通信。但這層保護究竟是如何實現的?HTTPS、SSL和TLS之間又存在著怎樣的聯系與區別?本文將深入剖析這些技術細節,帶你全…

Flutter 官方 LLM 動態 UI 庫 flutter_genui 發布,讓 App UI 自己生成 UI

今日&#xff0c;Flutter 官方正式發布了它們關于 AI 大模型的 package 項目&#xff1a; genui &#xff0c;它是一個非常有趣和前沿的探索類型的項目&#xff0c;它的目標是幫助開發者構建由生成式 AI 模型驅動的動態、對話式用戶界面&#xff1a; 也就是它與傳統 App 中“寫…

Redis常用數據結構及其底層實現

Redis常用數據結構主要有String List Set Zset Hash BitMap Hyperloglog Stream GeoString:Redis最常用的一種數據結構,Sting類型的數據存儲結構有三種int、embstr、raw1.int:用來存儲long以下的整形embstr raw 都是用來存字符串&#xff0c;其中小于44字節的字符串用embstr存 …

O3.4 opencv圖形拼接+答題卡識別

一圖形拼接邏輯導入必要的庫pythonimport cv2 import numpy as np import sys導入cv2庫用于圖像處理&#xff0c;numpy庫用于數值計算&#xff0c;sys庫用于與 Python 解釋器進行交互&#xff0c;例如退出程序。定義圖像顯示函數def cv_show(name, img):cv2.imshow(name, img)c…