c++八股文:c++編譯與內存管理

文章目錄

  • 1. c++內存管理
  • 2. 堆與棧
  • 3.變量定義與生命周期
  • 4.內存對齊
  • 5.內存泄露
  • 6.智能指針
  • 7.new 和 malloc 有什么區別
  • 8.delete和free的區別
  • 9.什么野指針,怎么產生的,如何避免野指針
  • 10.野指針和指針懸浮的區別
  • 11.字符串操作函數
  • 參考

1. c++內存管理

c++在運行程序時,內存被分為幾個不同的區域,每個區域負責不同的任務。c++程序使用的分區一般包括:棧區、堆區、全局/靜態變量存儲區、常量存儲區、代碼區。
區域名存放的數據生命周期
棧區局部變量、函數參數、函數返回值棧上的變量?命周期與其所在函數的執?周期相同
堆區動態分配的內存new、malloc?命周期由程序員顯式控制
全局/靜態存儲區全局變量和靜態變量整個程序運行期間
常量區常量,不允許修改程序運行結束自動釋放
代碼區代碼
  • 棧區:
    • 由編譯器自動存放和釋放,棧空間在進程生存周期一直都存在,當進程退出時,操作系統才會對棧空間進行回收。
    • 存放局部變量 、函數參數、函數返回值;
    • 函數的調用和返回通過棧來管理;
局部變量:
在函數或一個代碼塊內部聲明的變量,稱為局部變量。
它們只能被函數內部或者代碼塊內部的語句使用。
  • 堆區:

    • 堆?于存儲動態分配的內存的區域,由程序員?動分配和釋放;
    • 使? new 和 delete 或 malloc 和 free 來進?堆內存的分配和釋放;
  • 全局/靜態存儲區:

    • ?命周期是整個程序運?期間;
    • 在程序啟動時分配,程序結束時釋放;
    • 全局區存儲全局變量和靜態變量;
全局變量:
在所有函數外部定義的變量(通常是在程序的頭部),稱為全局變量。
全局變量的值在程序的整個生命周期內都是有效的。靜態變量:
在函數體內聲明一個靜態局部變量( Static Local Variable )。
它在函數運行結束后不會消失,并且只有聲明它的函數中能夠使用它。
聲明一個靜態局部變量的方法是在聲明局部變量前加上 static。
  • 常量區:

    • 存放的是常量,不允許修改,程序運行結束自動釋放。
  • 代碼區:

    • 存放代碼,不允許修改,但可以執行。編譯后的二進制文件存放在這里。

示例:

#include <iostream>
using namespace std;
/*
說明:C++ 中不再區分初始化和未初始化的全局變量、靜態變量的存儲區,如果非要區分下述程序標注在了括號中
*/
int g_var = 0; // g_var 在全局區(.data 段)
char *gp_var;  // gp_var 在全局區(.bss 段)int main()
{int var;                    // var 在棧區char *p_var;                // p_var 在棧區char arr[] = "abc";         // arr 為數組變量,存儲在棧區;"abc"為字符串常量,存儲在常量區char *p_var1 = "123456";    // p_var1 在棧區;"123456"為字符串常量,存儲在常量區static int s_var = 0;       // s_var 為靜態變量,存在靜態存儲區(.data 段)p_var = (char *)malloc(10); // 分配得來的 10 個字節的區域在堆區free(p_var);return 0;
}作者:LeetCode
鏈接:https://leetcode.cn/leetbook/read/cmian-shi-tu-po/vv6a76/
來源:力扣(LeetCode)
著作權歸作者所有。商業轉載請聯系作者獲得授權,非商業轉載請注明出處。

2. 堆與棧

棧和堆都是?于存儲程序數據的內存區域。棧是?種有限的內存區域,?于存儲局部變量、函數調?信息等。
堆是?種動態分配的內存區域,?于存儲程序運?時動態分配的數據。
棧上的變量?命周期與其所在函數的執?周期相同,?堆上的變量?命周期由程序員顯式控制,可以(使? new 或 malloc )和釋放(使? delete 或 free )。
棧上的內存分配和釋放是?動的,速度較快。?堆上的內存分配和釋放需要?動操作,速度相對較慢。

  • 申請方式:棧中存放的變量在編譯時由編譯器為其在棧上分配了空間,釋放時也由于函數調用的返回,棧的空間會自動進行回收。堆中存放的變量由程序運行時決定的,會有操作系統或者內存管理模塊來進行分配的。

3.變量定義與生命周期

c/c++變量有兩個非常重要的屬性生命周期和作用域,這兩個屬性分別從時間和空間兩個維度描述一個變量。
  • 作用域:作用域即一個變量可以被引用的范圍,常見的作用域可分為 6 種:全局作用域,局部作用域,語句作用域,類作用域,命名空間作用域和文件作用域。

    • 全局變量:具有全局作用域。只需要在一個源文件里定義,就可以作用于所有源文件。其他不包含全局變量定義的源文件,需要用extern關鍵字在次聲明全局變量 。
    • 靜態全局變量:具有文件作用域。它作用于定義它的文件里,不能作用到其它文件里,即被 static 關鍵字修飾過的變量具有文件作用域。這樣即使兩個文件里定義了相同名字的全局靜態變量,它們也不是相同的變量。
    • 局部變量:具有局部作用域。僅作用在函數內部,對于函數外部的程序來說不可見。
    • 局部靜態變量:具有局部作用域,它只被初始化一次,只對定義自己的函數體始終可見, 只有定義該變量的函數內部可以使用訪問和修改該變量。
  • 生命周期:變量可以被引用的時間段(變量的存在時間)

    • 全局變量:整個程序運行期間都會一直存在,都可以隨時訪問,當程序結束時,對應的變量則會自動銷毀,內存會被系統回收。
    • 局部變量:生命周期僅限于函數被調用階段,調用結束,該變量會自動銷毀。
    • 局部靜態變量:整個程序運行期間一直存在,只能被初始化一次。
  • 注意:

    • 全局變量定義在不要在頭文件中定義:如果在頭文件中定義全局變量,當該頭文件被多個文件 include 時,該頭文件中的全局變量就會被定義多次,編譯時會因為重復定義而報錯,因此不能再頭文件中定義全局變量。一般情況下我們將變量的定義放在 .cpp 文件中,一般在 .h 文件使用extern 對變量進行聲明。

4.內存對齊

  • 什么是內存對齊:內存對?是指數據在內存中的存儲起始地址是某個值的倍數。
    • ?多數計算機硬件要求基本數據類型的變量在內存中的地址是它們??的倍數。例如,?個 32 位整數通常需要在內存中對?到 4 字節邊界。
    • 內存對?可以提?訪問內存的速度。當數據按照硬件要求的對??式存儲時,CPU可以更?效地訪問內存,減少因為不對??引起的性能損失。
    • 許多計算機體系結構使?緩存?(cache line)來從內存中加載數據到緩存中。如果數據是對?的,那么?個緩存?可以裝載更多的數據,提?緩存的命中率。
    • 有些計算機架構要求原?性操作(?如原?性讀寫)必須在特定的內存地址上執?。如果數據不對?,可能導致?法執?原?性操作,進?引發競態條件。

5.內存泄露

  • 什么是內存泄露:內存泄漏并非指內存從物理上消失,而是指程序在運行過程中,由于疏忽或錯誤而失去了對該內存的控制,從而造成了內存的浪費。
  • 內存分類:
    • 堆內存泄漏:堆是動態分配的,一旦用戶申請了內存分配而為及時釋放,那么該部分內存在整個程序運行周期內都是被占用的,其他程序無法再使用這部分內存。我們在調用過程中使用 malloc、calloc、realloc、new 等分配內存時,使用完后要調用相應的 free 或 delete 釋放內存,否則這塊內存就會造成內存泄漏。
    • 系統資源泄露:主要指程序使?系統分配的資源?如 Bitmap,handle ,SOCKET 等沒有使?相應的函數釋放掉,導致系統資源的浪費,嚴重可導致系統效能降低,系統運?不穩定。
    • 沒有將基類的析構函數定義為虛函數:
      當基類指針指向?類對象時,如果基類的析構函數不是 virtual,那么?類的析構函數將不會被調?,?類的資源沒有正確是釋放,因此造成內存泄露。
  • 什么操作導致內存泄漏:指針指向改變,未釋放動態分配內存。
  • 如何防止內存泄漏:將內存的分配封裝在類中,構造函數分配內存,析構函數釋放內存;使?智能指針。
  • 智能指針有了解哪些:智能指針是為了解決動態分配內存導致內存泄露和多次釋放同?內存所提出的,C11標準中放在<memory>頭?件。包括:共享指針,獨占指針,弱指針。
  • 構造函數,析構函數要設為虛函數嗎,為什么?
    (1)析構函數
    析構函數需要。當派?類對象中有內存需要回收時,如果析構函數不是虛函數,不會觸發動態綁定,只會調?基類析構函數,導致派?類資源?法釋放,造成內存泄漏。
    (2)構造函數
    構造函數不需要,沒有意義。虛函數調?是在部分信息下完成?作的機制,允許我們只知道接??不知道對象的確切類型。 要創建?個對象,你需要知道對象的完整信息。 特別是,你需要知道你想要創建的確切類型。 因此,構造函數不應該被定義為虛函數。

6.智能指針

智能指針?于管理動態內存的對象,其主要?的是在避免內存泄漏和?便資源管理。
  • std::unique_ptr 獨占智能指針
  • std::shared_ptr 共享智能指針
  • std::weak_ptr 弱引?智能指

7.new 和 malloc 有什么區別

newmalloc
類型安全性是C++的運算符,可以為對象分配內存并調?相應的構造函數。是C語?庫函數,只分配指定??的內存塊,不會調?構造函數。
返回值返回的是具體類型的指針,?且不需要進?類型轉換。返回的是 void* ,需要進?類型轉換,因為它不知道所分配內存的?途。
內存分配失敗在內存分配失敗時會拋出 std::bad_alloc 異常。在內存分配失敗時返回 NULL 。
內存塊大小可以?于動態分配數組,并知道數組??。只是分配指定??的內存塊,不了解所分配內存塊的具體?途。
釋放內存方式會調?對象的析構函數,然后釋放內存。只是簡單地釋放內存塊,不會調?對象的析構函數。

8.delete和free的區別

deletefree
類型安全性會調?對象的析構函數,確保資源被正確釋放。不了解對象的構造和析構,只是簡單地釋放內存塊。
內存塊釋放后的?為釋放的內存塊的指針值會被設置為 nullptr ,以避免野指針。不會修改指針的值,可能導致野指針問題。
數組的釋放可以正確釋放通過 new[] 分配的數組。不了解數組的??,不適?于釋放通過 malloc 分配的數組

9.什么野指針,怎么產生的,如何避免野指針

野指針是指指向已被釋放的或?效的內存地址的指針。使?野指針可能導致程序崩潰、數據損壞或其他不可預測的?為。

怎么產生的野指針真么避免野指針
指針沒有初始化指針變量一定要初始化,可以初始化為nullptr
釋放后沒有置空指針在釋放內存后將指針置為 nullptr
返回局部變量的指針避免返回局部變量的指針
函數參數指針被釋放避免函數參數指針被釋放
使?智能指針(如 std::unique_ptr 和 std::shared_ptr )
注意函數參數的?命周期, 避免在函數內釋放調??傳遞的指針,或者通過引?傳遞指針

10.野指針和指針懸浮的區別

野指針是指向已經被釋放或者?效的內存地址的指針。通常由于指針指向的內存被釋放,但指針本身沒有被置為nullptr 或者重新分配有效的內存,導致指針仍然包含之前的內存地址。使?野指針進?訪問會導致未定義?為,可能引發程序崩潰、數據損壞等問題。
懸浮指針是指向已經被銷毀的對象的引?。當函數返回?個局部變量的引?,?調?者使?該引?時,就可能產?懸浮引?。訪問懸浮引?會導致未定義?為,因為引?指向的對象已經被銷毀,數據不再有效。

  • 區別:
野指針懸浮指針
關聯對象類型涉及指針類型設計引用類型
問題表現可能導致訪問已釋放或?效內存,引發崩潰或數據損壞可能導致訪問已銷毀的對象,引發未定義?為
產?原因野指針通常由于不正確管理指針?命周期引起懸浮指針通常由于在函數中返回局部變量的引?引起
如何避免懸浮指針避免在函數中返回局部變量的引?

11.字符串操作函數

  • strcpy(): char * strcpy(char *dest, const char *src)
    把從src地址開始且含有’\0’結束符的字符串復制到以dest開始的地址空間,返回值的類型為char*

  • strlen():size_t strlen (const char *s)
    計算給定字符串的?度。

  • strcat():char * strcat(char *dest, const char *src)
    作?是把src所指字符串添加到dest結尾處。

  • strcmp():int strcmp(const char *s1, const char *s2)
    ?較兩個字符串設這兩個字符串為s1,s2,
    若s1 == s2,則返回零
    若s1 < s2,則返回負數
    若s1 > s2,則返回正數

參考

Leetcodec++面試突破

代碼隨想錄——最強八股文

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

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

相關文章

LeetCode刷題--- 乘積為正數的最長子數組長度

個人主頁&#xff1a;元清加油_【C】,【C語言】,【數據結構與算法】-CSDN博客 個人專欄 力扣遞歸算法題 http://t.csdnimg.cn/yUl2I 【C】 ??????http://t.csdnimg.cn/6AbpV 數據結構與算法 ???http://t.csdnimg.cn/hKh2l 前言&#xff1a;這個專欄主要講述動…

ScheduledThreadPoolExecutor學習

簡介 ScheduledThreadPoolExecutor 是 Java 中的一個類&#xff0c;它屬于 java.util.concurrent 包。這個類是一個線程池&#xff0c;用于在給定的延遲后運行命令&#xff0c;或者定期地執行命令。它是 ThreadPoolExecutor 的一個子類&#xff0c;專門用于處理需要定時或周期…

解釋索引是什么以及它們是如何提高查詢性能的

索引在數據庫管理系統中是一個重要的數據結構&#xff0c;用于幫助快速檢索數據庫表中的數據。它可以被看作是一個指向表中數據的指針列表&#xff0c;這些指針按照某種特定的順序&#xff08;如字母順序或數字順序&#xff09;排列。索引的工作原理類似于書籍的目錄&#xff1…

Python爬蟲實戰第二例【二】

零.前言&#xff1a; 本文章借鑒&#xff1a;Python爬蟲實戰&#xff08;五&#xff09;&#xff1a;根據關鍵字爬取某度圖片批量下載到本地&#xff08;附上完整源碼&#xff09;_python爬蟲下載圖片-CSDN博客 大佬的文章里面有API的獲取&#xff0c;在這里我就不贅述了。 一…

kitex 入門和基于grpc的使用

&#x1f4d5;作者簡介&#xff1a; 過去日記&#xff0c;致力于Java、GoLang,Rust等多種編程語言&#xff0c;熱愛技術&#xff0c;喜歡游戲的博主。 &#x1f4d7;本文收錄于kitex系列&#xff0c;大家有興趣的可以看一看 &#x1f4d8;相關專欄Rust初階教程、go語言基礎系…

【Web】青少年CTF擂臺挑戰賽 2024 #Round 1 wp

好家伙&#xff0c;比賽結束了還有一道0解web題是吧( 隨緣寫點wp(簡單過頭&#xff0c;看個樂就好) 目錄 EasyMD5 PHP的后門 PHP的XXE Easy_SQLi 雛形系統 EasyMD5 進來是個文件上傳界面 說是只能上傳pdf&#xff0c;那就改Content-Type為application/pdf&#xff0c;改…

11.盛最多水的容器

題目&#xff1a;給定一個長度為 n 的整數數組 height 。有 n 條垂線&#xff0c;第 i 條線的兩個端點是 (i, 0) 和 (i, height[i]) 。 找出其中的兩條線&#xff0c;使得它們與 x 軸共同構成的容器可以容納最多的水。 返回容器可以儲存的最大水量。 解題思路&#xff1a;可以…

判斷閏年(1000-2000)

判斷規則&#xff1a;1.能被4整除&#xff0c;不能被100整除是閏年,2.能被400整除是閏年 #include <stdio.h>int is_leap_year(int n){if((n % 400 0)||((n % 4 0)&&(n % 100 ! 0)))return 1;elsereturn 0; } int main() {int i 0;int count 0;for(i 1000;…

基于PHP的在線英語學習平臺

有需要請加文章底部Q哦 可遠程調試 基于PHP的在線英語學習平臺 一 介紹 此在線英語學習平臺基于原生PHP開發&#xff0c;數據庫mysql。系統角色分為學生&#xff0c;教師和管理員。(附帶參考設計文檔) 技術棧&#xff1a;phpmysqlphpstudyvscode 二 功能 學生 1 注冊/登錄/…

C++/Python簡單練手題

前言 最近需要開始使用python&#xff0c;但是對python了解的并不多&#xff0c;于是先從很早之前剛學C時寫過的一些練手題開始&#xff0c;使用python來實現相同的功能&#xff0c;在溫習python基礎語法的同時&#xff0c;也一起來感受感受python的魅力 99乘法表 c&#xf…

kettle開發-Day43-加密環境下運行作業

前言&#xff1a; 金三銀四&#xff0c;開年第一篇我們來介紹下&#xff0c;怎么在加密情況下運行我們的kettle作業及任務。無疑現在所有企業都認識到加密的重要性&#xff0c;加密后的文件在對外傳輸的時候不能被訪問&#xff0c;訪問時出現一堆亂碼&#xff0c;同時正常的應用…

1分鐘學會Python字符串前后綴與編解碼

1.前綴和后綴 前綴和后綴指的是&#xff1a;字符串是否以指定字符開頭和結尾 2.startswith() 判斷字符串是否以指定字符開頭&#xff0c;若是返回True&#xff0c;若不是返回False str1 "HelloPython"print(str1.startswith("Hello")) # Trueprint…

Navicat Premium 16:打破數據庫界限,實現高效管理mac/win版

Navicat Premium 16是一款功能強大的數據庫管理工具&#xff0c;旨在幫助用戶更輕松地連接、管理和保護各種數據庫。該軟件支持多種數據庫系統&#xff0c;如MySQL、Oracle、SQL Server、PostgreSQL等&#xff0c;并提供了直觀的圖形界面&#xff0c;使用戶能夠輕松地完成各種數…

【力扣白嫖日記】585.2016年的投資

前言 練習sql語句&#xff0c;所有題目來自于力扣&#xff08;https://leetcode.cn/problemset/database/&#xff09;的免費數據庫練習題。 今日題目&#xff1a; 585.2016年的投資 表&#xff1a;Person 列名類型pidinttiv_2015floattiv_2016floatlatfloatlonfloat pid …

AI也來打摜蛋,難道人工智能也能當領導?

在人工智能&#xff08;AI&#xff09;的研究領域中&#xff0c;游戲被視為現實世界的簡化模型&#xff0c;常常是研究的首選平臺。這些研究主要關注游戲代理的決策過程。例如&#xff0c;中國的傳統卡牌游戲“摜蛋”&#xff08;字面意思是“扔雞蛋”&#xff09;就是一個挑戰…

Unity(第十七部)Unity自帶的角色控制器

組件Character Controller 中文角色控制器 using System.Collections; using System.Collections.Generic; using UnityEngine;public class player : MonoBehaviour {private CharacterController player;void Start(){player GetComponent<CharacterController>();}v…

對于爬蟲的學習

本地爬取 package MyApi.a08regexdemo;import java.util.regex.Matcher; import java.util.regex.Pattern;public class RegexDemo03 {public static void main(String[] args) {//要求&#xff1a;找出里面所有javaxxString str"Java自從95年問世以來&#xff0c;經歷了…

騰訊日常實習-數據科學-初試涼經

個人背景&#xff1a;雙985 騰訊會議面了一個小時左右&#xff0c;過程如下&#xff1a; 1.面試官首先介紹了一下部門&#xff08;騰訊云&#xff09;的情況和業務方向。 2.讓我介紹一下自己&#xff08;目前情況&#xff0c;科研經歷&#xff0c;項目經歷&#xff09;。 3.就我…

HarmonyOS—編譯構建概述

編譯構建是將應用/服務的源代碼、資源、第三方庫等&#xff0c;通過編譯工具轉換為可直接在硬件設備上運行的二進制機器碼&#xff0c;然后再將二進制機器碼封裝為HAP/APP軟件包&#xff0c;并為HAP/APP包進行簽名的過程。其中&#xff0c;HAP是可以直接運行在模擬器或真機設備…

牛皮癬發作和復發的觸發因素

谷禾健康 銀屑病&#xff0c;又叫牛皮癬&#xff0c;會導致出現皮疹伴發癢的鱗狀斑塊&#xff0c;最常見于膝蓋、肘部、軀干和頭皮。通常呈周期性發展&#xff0c;發作數周或數月&#xff0c;然后消退一段時間&#xff0c;長期的發作和復發會給患者帶來很大的痛苦和困擾&#x…