【C/C++ new/delete和malloc/free的異同及原理】

new/delete和malloc/free都是用于在C++(以及C語言在malloc/free的情況下)中動態申請和釋放內存的機制,但它們之間存在一些顯著的異同點。以下是對這兩組函數/運算符的異同點的詳細分析:

相同點

  1. 目的相同:兩者都用于在堆(heap)上動態地分配和釋放內存。
  2. 手動管理:無論是new/delete還是malloc/free,都需要程序員手動進行內存的分配和釋放,以避免內存泄漏。

不同點

  1. 類型與來源
    new/delete:是C++的運算符,支持重載,可以與C++的類特性(如構造函數、析構函數)緊密集成。
    malloc/free:是C語言(及C++兼容)的標準庫函數,分別定義在<stdlib.h>(C語言)和(C++)頭文件中。
  2. 內存分配與初始化
    new:能夠自動根據對象的類型計算所需內存大小,并在分配內存后自動調用對象的構造函數進行初始化(如果是類類型的對象)。
    malloc:需要程序員手動計算所需內存大小,并且分配的內存不會自動初始化,通常包含未定義的值。
  3. 返回值
    new:返回指向分配的內存的指針,該指針的類型是所分配對象的類型。
    malloc:返回void*類型的指針,指向分配的內存,需要程序員根據需要進行類型轉換。
  4. 錯誤處理
    new:如果內存分配失敗,會拋出std::bad_alloc異常。
    malloc:如果內存分配失敗,會返回NULL(在C++11及以后,推薦使用nullptr)。
  5. 內存釋放
    delete:在釋放內存時,會調用對象的析構函數(如果是類類型的對象),然后釋放內存。
    free:僅釋放之前通過malloc分配的內存,不會調用任何析構函數。
  6. 數組支持
    new/delete:對于數組,有專門的語法new 類型[大小]和delete[] 指針來分配和釋放內存。
    malloc/free:對于數組,只需在malloc中指定數組總大小(每個元素的類型大小乘以元素數量),并在free中傳遞指向數組首元素的指針。但注意,malloc不會自動處理數組元素的構造或析構。
  7. 類型安全
    new:提供了更好的類型安全,因為返回的是具體類型的指針,編譯器可以進行類型檢查。
    malloc:由于返回void*類型,需要程序員進行類型轉換,這可能引入類型錯誤。
  8. 性能
    在底層實現上,new/delete通常是對malloc/free的封裝,因此它們的性能差異主要取決于封裝層的開銷。在大多數情況下,這種差異可以忽略不計,但在性能敏感的應用中可能需要考慮。
現在開始添加阿秀總結部分(很清晰、易懂,非常建議學習
  1. new是類型安全的,malloc不是。例如:

    int*p=newfloat[2];//編譯錯誤
    int *p = (int*)malloc(2*sizeof(double));//編譯無錯誤
    
  2. new調用名為operator new的標準庫函數分配足夠空間并調用相關對象的構構造函數,delete對指針所指對象運行適當的析構函數,然后通過調用名為perator delete的標準庫函數釋放該對象所用內存。后者均沒有相關調用。

  3. new是封裝了malloc,直接free不會報錯,但是這只是釋放內存,而不會析構對象

  4. new和delete是如何實現的?
    new的實現過程是:首先調用名為operator new的標準庫函數,分配足夠大的原始為類型化的內存,以保存指定類型的一個對象;接下來運行該類型的一個構造函數,用指定初始化構造對象;最后返回指向新分配并構造后的的對象的指針;
    delete的實現過程:對指針指向的對象運行適當的析構函數;然后通過調用名為operator delete的標準庫函數釋放該對象所用內存;

  5. malloc和new的區別?
    malloc和free是標準庫函數,支持覆蓋;new和delete是運算符,支持重載。
    malloc僅僅分配內存空間,free僅僅回收空間,不具備調用構造函數和析構函數功能,用malloc分配空間存儲類的對象存在風險;new和delete除了分配回收功能外,還會調用構造函數和析構函數。
    malloc和free返回的是void類型指針(必須進行類型轉換),new和delete返回的是具體類型指針。

  6. 既然有了malloc/free,C++中為什么還需要new/delete呢?直接用malloc/free不好嗎?
    malloc/free和new/delete都是用來申請內存和回收內存的。
    在對非基本數據類型的對象使用的時候,對象創建的時候還需要執行構造函數,銷毀的時候要執行析構函數。而malloc/free是庫函數,是已經編譯的代碼,所以不能把構造函數和析構函數的功能強加給malloc/free,所以new/delete是必不不可少的。

  7. 被free回收的內存是立即返還給操作系統嗎?
    不是的,被free回收的內存會首先被ptmalloc使用雙鏈表保存起來,當用戶下一次申請內存的時候,會嘗試從這些內存中尋找合適的返回。這樣就避免了頻繁的系統調用,占用過多的系統資源。同時ptmalloc也會嘗試對小塊內存進行合并,避免過多的內存碎片。

總結

new/delete和malloc/free各有其適用場景。在C++程序中,由于new/delete能夠與C++的類特性更好地集成,因此通常是首選的內存分配方式。然而,在處理與C語言的接口或需要更低級內存操作的情況下,malloc/free仍然有其不可替代的作用。重要的是,無論使用哪種方式,都應確保及時釋放分配的內存,以避免內存泄漏。

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

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

相關文章

C++編程邏輯講解step by step:類之間的交互

題目 設計一個點類Point&#xff0c;再設計一個矩形類&#xff0c;矩形類使用Point類的兩個坐標點作為矩形的對角頂點。并可以輸出4個坐標值和面積。 分析 1.點類&#xff0c;自然維護的是一個點的坐標&#xff0c; #include < iostream > using namespace std; class …

【C語言基礎知識點】C語言-使用 fgets 讀取包含空格的字符串

使用 fgets 讀取包含空格的字符串 // 使用 fgets 讀取包含空格的字符串 #include <stdio.h> #include <string.h> int main() { char name[100]; printf("Enter your name: "); fgets(name, sizeof(name), stdin); // 移除可能讀取到的換行符 n…

Matlab/simulink三段式電流保護

電流1段仿真波形如下所示 電流2段仿真波形如下所示 電流3段仿真波形如下所示

Centos7安裝Minio筆記

一、Minio概述 Minio是一款開源的對象存儲服務器&#xff0c;可以運行在多種操作系統上&#xff0c;包括Linux、Windows和MacOS等。提供一種簡單、可擴展、高可用的對象存儲解決方案&#xff0c;支持多種數據格式&#xff0c;包括對象、塊和文件等。Minio是一款強大、靈活、可…

WCCI 2024第三彈:忍者表演驚艷全場,盛大晚宴不容錯過

WCCI 2024第三彈&#xff1a;忍者表演驚艷全場&#xff0c;盛大晚宴不容錯過&#xff01; 會議之眼 快訊 會議介紹 IEEE WCCI&#xff08;World Congress on Computational Intelligence&#xff09;2024&#xff0c;即2024年IEEE世界計算智能大會&#xff0c;于6月30日至7月…

【前端知識】一篇速成 建議收藏

HTML基礎概念 正式敲代碼之前呢,我們先來看幾個概念: 0 靜態網頁和動態網頁 靜態網頁: 頁面的內容和顯示效果就基本上不會發生變化了--除非你修改頁面代碼。 動態網頁: 頁面代碼雖然沒有變&#xff0c;但是顯示的內容卻是可以隨著時間、環境或者數據庫操作的結果而發生改變的…

【康復學習--LeetCode每日一題】3099. 哈沙德數

題目&#xff1a; 如果一個整數能夠被其各個數位上的數字之和整除&#xff0c;則稱之為 哈沙德數&#xff08;Harshad number&#xff09;。給你一個整數 x 。如果 x 是 哈沙德數 &#xff0c;則返回 x 各個數位上的數字之和&#xff0c;否則&#xff0c;返回 -1 。 示例 1&a…

【Qt知識】window frame 對窗口坐標的影響

在Qt中&#xff0c;窗口框架&#xff08;Window Frame&#xff09;對Widget的尺寸計算和坐標定位有著直接的影響&#xff0c;這主要是因為窗口框架本身占據了一定的空間&#xff0c;包括標題欄、最小化/最大化/關閉按鈕以及邊框。這部分額外的空間在不同的應用場景下需要被考慮…

windows非白名單exe監控并殺死

需求&#xff1a;孩子在家用電腦上網課&#xff0c;總是悄悄打開游戲或視頻軟件 方案&#xff1a;指定白名單exe&#xff0c;打開非白名單的就自動被殺死&#xff0c;并記錄日志供查看 不知道是否還有更好的結果方案&#xff1f; import psutil import time import logging#…

2024.7.4 刷題總結

2024.7.4 **每日一題** 3086.拾起k個1需要的最少行動次數&#xff0c;在這道題我們可以把0看成空位&#xff0c;第二種操作相當于把一個1移動到和它相鄰的空位上&#xff0c;而第一種操作則是貪心地把和當前下標相鄰的0變成1;當maxchanges較大時&#xff0c;優先使用第一種操作…

第二十條:與抽象類相比,優先選擇接口

要定義多種實現的類型&#xff1a;JAVA有兩種機制&#xff1a;接口和抽象類。這兩種機制都支持為某些實例方法提供實現&#xff0c;但二者有個重要的區別&#xff1a;要實現由抽象類定義的類型&#xff0c;這個類必須是抽象類的子類。因為Java只允許單繼承&#xff0c;對抽象類…

使用SSE實現echarts數據實時更新

區別 SSE 和 WebSocket 原理和實現方式的區別 SSE( Server-Sent Events) SSE 是基于傳統的 HTTP 協議實現的&#xff0c;采用了長輪詢&#xff08;long-polling&#xff09;機制。客戶端通過向服務器發送一個 HTTP 請求&#xff0c;服務器保持連接打開并周期性地向客戶端發送…

內網穿透--利用everything實現目錄映射

免責聲明:本文僅做技術交流與學習... 目錄 來源文章 frp下載網址 為了隱藏: 演示: 1-靶機的everything開啟http服務 2-Linux服務器: 3-靶機windows: 4-最后訪問: 來源文章 滲透測試技巧|Everything的利用 frp下載網址 Release v0.58.1 fatedier/frp GitHub 為了隱…

協程調度模塊

什么是協程和協程調度&#xff1f; 基本概念 協程 協程是一種比線程更輕量級的并發編程結構&#xff0c;它允許在函數執行過程中暫停和恢復執行狀態&#xff0c;從而實現非阻塞式編程。協程又被稱為用戶級線程&#xff0c;這是由于協程包括上下文切換在內的全部執行邏輯都是…

WAIC熱點聚焦|具身智能簡介:AI新浪潮的領跑者

WAIC熱點聚焦|具身智能簡介&#xff1a;AI新浪潮的領跑者 引言 隨著"具身智能"&#xff08;Embodied Intelligence&#xff09;的火熱討論&#xff0c;2024年標志著人機交互新時代的開啟。在大模型技術的推動下&#xff0c;機器人響應語音指令成為現實&#xff0c;…

Linux Rsyslog+LogAnalyzer+MariaDB部署日志服務器

文章目錄 Linux RsyslogLogAnalyzerMariaDB部署日志服務器1 環境準備1.1 服務器端安裝LAMP環境1.2 服務啟動并加入開機啟動1.2.1 Apache1.2.2 MariaDB1.2.3 Php 2 Rsyslog服務端安裝及配置2.1 安裝Rsyslog及Rsyslog連接MySQL的模塊2.2 導入rsyslog-mysql數據庫文件2.3 查看剛導…

深入淺出:npm常用命令詳解與實戰

theme: smartblue npm是什么 npm&#xff08;Node Package Manager&#xff09;是Node.js平臺的默認包管理器&#xff0c;它讓JavaScript開發者能夠輕松地共享、管理和使用彼此編寫的代碼模塊。npm不僅僅是一個安裝工具&#xff0c;它還是一個全面的生態系統&#xff0c;用于發…

【YOLOv5/v7改進系列】替換損失函數為WIOU、CIOU、GIOU、SIOU、DIOU、EIOU、Focal C/G/S/D/EIOU等

一、導言 在目標檢測任務中&#xff0c;損失函數的主要作用是衡量模型預測的邊界框&#xff08;bounding boxes&#xff09;與真實邊界框之間的匹配程度&#xff0c;并指導模型學習如何更精確地定位和分類目標。損失函數通常由兩部分構成&#xff1a;分類損失&#xff08;用于…

RabbitMQ入門教程(精細版二帶圖)

目錄 六 RabbitMQ工作模式 6.1Hello World簡單模式 6.1.1 什么是簡單模式 6.1.2 RabbitMQ管理界面操作 6.1.3 生產者代碼 6.1.4 消費者代碼 6.2 Work queues工作隊列模式 6.2.1 什么是工作隊列模式 6.2.2 RabbitMQ管理界面操作 6.2.3 生產者代碼 6.2.4 消費者代碼 …

清理測試數據用truncate還是delete

truncate和delete的區別&#xff0c;我相信大家都清楚。 truncate會清空表的全部數據&#xff0c;且自增主鍵會重置&#xff1b;而delete可以按條件刪除&#xff0c;且自增主鍵不會重置。 我們日常測試過程中經常要刪除掉測試數據&#xff0c;那么應該用truncate刪&#xff0c…