C++高級語言程序設計第四章_第1頁
C++高級語言程序設計第四章_第2頁
C++高級語言程序設計第四章_第3頁
C++高級語言程序設計第四章_第4頁
C++高級語言程序設計第四章_第5頁
已閱讀5頁,還剩28頁未讀 繼續免費閱讀

下載本文檔

版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領

文檔簡介

C++高級語言程序設計第四章數組—從一維到多維,從靜態到動態Contents本章目錄數組與指針的核心知識體系概覽01一維數組基礎與應用02指針與指針數組03二維數組與多維數組04數組與函數及動態存儲05字符數組與字符串處理CHAPTER01一維數組基礎與應用掌握連續內存中同類元素的組織方式與訪問規則C++FUNDAMENTALS一維數組的定義與初始化一維數組是C++中存儲同類型數據的連續內存結構,定義時需指定類型、名稱和常量大小,支持完全初始化、部分初始化和自動推斷三種初始化方式,未顯式初始化的元素默認為零值。C++編程環境·數組定義代碼實拍01基本語法類型數組名[常量]方括號內必須是編譯期常量02完全/部分初始化逐個賦值所有元素,或僅賦前幾個、剩余自動置零03自動推斷大小省略方括號內數字,編譯器根據初值列表自動確定長度04默認值差異全局數組默認0(靜態區),局部數組為垃圾值(棧區)MemoryLayout一維數組的內存布局與下標訪問數組元素在內存中連續排列,數組名即首元素地址,下標訪問的本質是"基址+偏移量"的地址運算,理解這一機制是掌握指針與數組關系的前提。01連續存儲inta[5]在內存中占用5×4=20字節連續空間,元素a[0]到a[4]依次排列,相鄰元素地址差恰好為sizeof(int)即4字節20B02數組名即地址數組名a等價于&a[0],是常量指針(不可修改a本身的指向),通過a可獲取整個數組的起始內存位置a≡&a[0]03下標運算本質a[i]被編譯器轉換為*(a+i),即從首地址偏移i個元素單位后取值,因此下標從0開始、最大為n?1*(a+i)04越界訪問風險C++不進行數組邊界檢查,訪問a[5]或a[?1]不會報編譯錯誤,但會讀寫非法內存,導致程序崩潰或數據損壞無邊界檢查ARRAYFUNDAMENTALS一維數組的典型應用模式數組的核心操作模式包括遍歷求和、極值查找和元素逆序,這些模式體現了'循環+條件判斷'的基本算法思想,是后續排序、查找等復雜算法的構建基石。遍歷求和與統計用for循環遍歷所有元素累加求和,結合計數器計算平均值,是最基礎的數組操作范式O(n)極值查找(打擂臺法)將a[0]設為初始最大/最小值,逐一與后續元素比較并更新,遍歷一輪即可找到全局極值打擂臺法數組逆序(首尾交換法)設置頭尾兩個下標i=0和j=n-1,交換a[i]與a[j]后i++、j--,循環n/2次完成逆序n/2次數組拷貝與比較C++不支持數組整體賦值(a=b非法),必須逐元素拷貝;比較兩個數組也需逐元素判斷逐元素SortingAlgorithms一維數組經典應用:排序算法冒泡排序與選擇排序是基于數組的兩種基礎排序算法,均通過嵌套循環實現元素重排,理解其原理有助于掌握算法設計中的比較-交換范式與復雜度分析方法。冒泡排序外層循環控制輪數(n?1輪),內層循環相鄰元素兩兩比較,若a[j]>a[j+1]則交換,每輪將當前最大值沉底。n?1輪沉底選擇排序每輪從未排序區間選出最小元素的下標,與未排序區間首元素交換位置,逐步構建有序前綴。最小值選擇復雜度分析兩種算法時間復雜度均為O(n2),空間復雜度O(1),屬于原地排序;冒泡排序可通過設置標志位提前終止優化。O(n2)·O(1)標準庫推薦C++標準庫提供std::sort()函數(位于<algorithm>頭文件),底層為快速排序優化實現,實際開發中推薦使用。std::sort()MemoryArchitecture變量的存儲類型與內存分區C++程序運行時內存分為棧區、堆區、全局/靜態存儲區和代碼區四大區域,變量的存儲類型決定了其內存位置、生命周期和訪問方式。四種存儲類型對照表存儲類型適用范圍內存區域生命周期關鍵特點auto局部變量(默認)棧區函數/代碼塊執行周期自動分配釋放,無需顯式寫autostatic局部/全局變量全局/靜態存儲區整個程序運行周期局部static僅初始化1次,全局static限制文件作用域extern全局變量聲明全局/靜態存儲區整個程序運行周期用于跨文件共享全局變量(僅聲明不定義)register局部變量(頻繁使用)寄存器(或棧區)函數/代碼塊執行周期建議存寄存器提速,不能取地址(&)棧區Stack存放局部變量和函數參數,由編譯器自動分配和釋放,空間有限但訪問速度快,普通局部數組即分配在此。堆區Heap由程序員通過new/delete手動管理的動態內存區域,空間大但需手動釋放,動態數組即分配在堆區。全局/靜態存儲區存放全局變量和static修飾的變量,程序啟動時分配、結束時釋放,static局部變量僅初始化一次且值持久保留。寄存器Register建議編譯器存入CPU寄存器以提升頻繁訪問變量的速度,但不能對其取地址(&運算非法),實際存儲位置由編譯器決定。四種存儲類型分別對應不同的內存區域和生命周期管理方式,直接影響數組和變量的行為特征。SCOPERULES標識符的作用域與可見性規則C++標識符的作用域分為函數原型、塊、函數和文件四個層次,遵循'就近屏蔽'原則——內層作用域的同名標識符會隱藏外層定義,正確理解作用域規則是避免變量命名沖突和邏輯錯誤的關鍵。函數原型作用域僅在函數聲明的參數列表中有效,如voidfun(inta)中的a只到原型結束,函數定義時可使用不同參數名參數列表塊作用域由{}界定,如函數體、if/for代碼塊內的變量;嵌套塊中內層變量會屏蔽外層同名變量,退出內層塊后外層變量恢復可見嵌套屏蔽文件作用域全局變量和函數的默認作用域,從定義位置到文件末尾均可見;加static修飾后限制為當前文件內部使用,防止跨文件沖突static同名屏蔽陷阱若局部變量與全局變量同名(如都叫num),函數內優先使用局部變量,全局變量被隱藏,需通過作用域解析運算符::訪問全局版本::CHAPTER02指針與指針數組深入理解地址運算、指針與數組的等價關系C++FUNDAMENTALS指針的基本概念與核心操作指針是存儲內存地址的變量,通過取地址(&)和解引用(*)兩個互逆運算符實現地址與值的轉換,指針的類型決定了解引用時讀取的字節數,正確使用指針是C++高效內存操作的基礎。01定義語法'類型*指針名',如int*p;類型決定解引用時讀取的字節數,int讀4字節,double讀8字節。TYPE*PTR02取地址與解引用&獲取變量內存地址,如p=&a;*通過地址訪問目標值,*p=10等價于修改a的值。&?*03指針自身占用64位系統上指針變量占8字節、32位占4字節,與所指向數據類型的大小無關。8BYTE04野指針與空指針未初始化的指針指向隨機地址,極其危險;應初始化為nullptr,避免非法內存訪問導致崩潰。=NULLPTRC/Pointer&Array指針與數組的等價關系數組名本質上是指向首元素的常量指針,a[i]與*(a+i)在編譯器層面完全等價,指針算術運算使得通過指針遍歷數組既高效又靈活,但數組名與指針變量在sizeof運算和賦值行為上存在本質差異。數組名即首地址inta[5]中a等價于&a[0],類型為int*,但a是常量指針,不可執行a++或賦值操作。a≡&a[0]下標與指針等價a[i]被編譯器轉換為*(a+i),p[i]也等價于*(p+i),可通過指針變量訪問數組元素。a[i]=*(a+i)指針算術運算p+1不是地址值加1,而是跳過一個元素大小(如int指針+1跳過4字節)。p+1→+4Bsizeof關鍵區別sizeof(a)返回數組總字節20,sizeof(p)僅返回指針大小8B;數組名不可賦值,指針可以。20Bvs8BC++·Memory指針數組的定義與典型應用指針數組是元素類型為指針的數組,每個元素存儲一個內存地址,常用于管理長度不一的字符串集合或構建不規則的二維數據結構,是C++中實現靈活數據組織的重要工具。大學生編程學習場景Syntax定義語法:int*pArr[5]表示含5個int指針的數組,每個元素是獨立指針變量,可分別指向不同int變量或數組String字符串管理:char*names[]中每個指針指向不同長度字符串常量,比二維字符數組節省內存且使用靈活Compare與數組指針區別:指針數組是多個獨立指針集合(每行可不同長),int(*p)[5]是指向整行的單個指針Usage典型場景:main函數參數argv就是指針數組,操作系統將命令行參數作為字符串數組傳遞給程序POINTER·ARRAYTRAVERSAL指針運算與數組遍歷方式對比C++中遍歷數組有下標法和指針法兩種基本方式,底層都基于"基址+偏移"的地址運算,指針法通過直接操作內存地址在某些場景下更靈活高效,兩個同數組指針相減可得元素間距。METHOD01下標法遍歷for(inti=0;i<n;i++)a[i],寫法直觀易讀,編譯器內部將a[i]轉換為*(a+i)執行,是初學者的首選方式。a[i]→*(a+i)METHOD02指針法遍歷int*p=a;*(p+i)或*p++,直接操作地址,在早期編譯器中比下標法效率更高。直接地址操作OPERATION01指針遞增p++使指針移向下一個元素,地址增加sizeof(類型)字節;p--反向移動,可靈活實現正向和反向遍歷。sizeof(T)步進OPERATION02指針相減若p和q指向同一數組,p?q的結果為兩指針間的元素個數,常用于計算子數組長度。ptrdiff_tCHAPTER03二維數組與多維數組從矩陣思維到行列優先的內存映射機制C/C++·數組與指針二維數組的定義與初始化方式二維數組在概念上表現為行列矩陣,但物理上仍是一維連續存儲,定義時必須明確列數(行數可省略),初始化支持按行分組、按序展開和部分初始化三種方式。01定義語法類型數組名[行數][列數],如inta[3][4]定義3行4列共12個int元素,總占用3×4×4=48字節連續內存48字節02按行分組初始化inta[2][3]={{1,2,3},{4,5,6}},外層花括號表示行,內層花括號表示每行的列元素,寫法最直觀{{…},{…}}03按序展開初始化inta[2][3]={1,2,3,4,5,6},按內存中元素排列順序依次賦值,編譯器自動按列數換行{1,2,3,4,5,6}04行數可省略列數不可省inta[][3]={1,2,3,4,5,6},編譯器根據總元素數和列數自動推算行數為2,但列數必須顯式指定a[][3]MEMORYMODEL二維數組的行優先存儲機制C++二維數組采用行優先方式將矩陣映射到一維連續內存中,元素a[i][j]的實際地址為"首地址+(i×列數+j)×元素大小"行優先存儲inta[3][4]在內存中按a[0][0]…a[0][3]、a[1][0]…a[2][3]的順序連續排列48字節地址計算公式a[i][j]地址=a+(i×COLS+j)×sizeof(元素類型),COLS為列數i×C+j行優先遍歷更高效外層行、內層列使內存訪問連續,CPU緩存命中率更高;列優先遍歷導致緩存頻繁失效緩存命中與列優先的區別Fortran/MATLAB采用列優先存儲,跨語言傳遞矩陣數據時需特別注意內存排列差異Fortran/MATLABApplicationScenarios二維數組的典型應用場景二維數組是矩陣運算、網格數據和圖像處理的基礎數據結構,通過行列索引可高效訪問和修改元素,在科學計算、游戲開發和計算機視覺等領域有廣泛應用。矩陣運算01矩陣加法對應元素相加C[i][j]=A[i][j]+B[i][j],要求兩矩陣行列數相同,用雙重循環實現02矩陣轉置行列互換B[j][i]=A[i][j],原地轉置需注意方陣與非方陣的不同處理策略03矩陣乘法C[i][j]=ΣA[i][k]×B[k][j],需三重循環,時間復雜度O(n3),是線性代數運算的核心網格與圖像01棋盤/地圖表示用二維數組存儲網格狀態(如intboard[8][8]),每個元素記錄格子信息02灰度圖像處理元素對應像素亮度值(0-255),圖像濾波、邊緣檢測等算法均基于鄰域運算03動態規劃表格DP算法中常用二維數組存儲子問題結果,如背包問題dp[i][j]表示前i個物品容量j的最優解C++FUNDAMENTALS多維數組與現代C++替代方案C++支持任意維度的數組但實際使用中維度很少超過三維,因為內存占用和代碼復雜度會急劇增長;現代C++推薦使用std::vector替代原生數組,獲得動態大小、自動內存管理和安全邊界檢查等優勢。多維數組定義三維數組定義如inta[2][3][4],共24個元素,可理解為"二維數組的數組";更高維度語法類似但可讀性和內存開銷急劇上升,實際開發中建議謹慎使用。維度示例2×3×4內存連續布局多維數組內存仍為一維連續:a[D1][D2][D3]中元素a[i][j][k]的偏移量為(i×D2×D3+j×D3+k)×sizeof(類型),編譯器自動完成多維到一維的地址映射。存儲特性連續內存原生數組局限大小必須在編譯期確定、不支持整體賦值、傳遞給函數時退化為指針丟失長度信息、無數組越界檢查,這些缺陷導致原生數組在現代C++中逐漸被淘汰。主要缺陷4項局限std::vector替代vector<int>v(10)創建動態數組,支持push_back擴容、size()獲取長度、at()安全訪問,是現代C++的首選容器,徹底解決了原生數組的安全隱患。核心優勢動態擴容CHAPTER04數組與函數及動態存儲掌握數組參數傳遞機制與堆區內存的動態管理C++·FUNDAMENTALS數組作為函數參數的三種方式數組作為函數參數時會自動退化為指向首元素的指針,丟失原始大小信息,因此必須額外傳遞長度參數;理解這一退化機制是正確設計數組處理函數和避免緩沖區溢出錯誤的關鍵。01voidfunc(inta[],intn)—形式上寫數組但實際傳遞的是指針,a[]等價于*a,函數內sizeof(a)只得到指針大小inta[]02voidfunc(int*a,intn)—與方式一完全等價,更明確地表達了"傳遞的是地址而非整個數組"的事實int*a03voidfunc(int(&a)[5])—通過數組引用傳遞,保留了數組類型和大小信息,但大小必須在編譯期確定,靈活性受限(&a)[5]04由于退化機制,函數無法獲知數組大小,必須額外傳入n參數或用begin/end指針對,否則極易導致越界訪問n/begin·endC++MemoryManagement動態內存分配:new與delete操作符new/delete是C++在堆區進行動態內存管理的核心操作符,支持運行時按需分配和釋放內存,但必須嚴格配對使用,否則將導致內存泄漏或程序崩潰。new操作符在堆區按需分配內存,int*p=newint(10)分配單個變量;int*arr=newint[n]支持運行時變量長度的數組分配。newint(n)delete操作符釋放堆區內存,deletep釋放單個對象;delete[]arr釋放數組。必須與new嚴格配對,new[]配delete[],不可混用。delete[]arr內存泄漏風險忘記用delete釋放已分配內存,該內存將無法被再次使用,長期運行中累積的泄漏最終會耗盡系統資源。MemoryLeak智能指針替代unique_ptr和shared_ptr自動管理動態內存生命周期,離開作用域時自動釋放,大幅降低出錯風險。SmartPointerMEMORYMANAGEMENT動態數組的創建、使用與管理動態數組通過new在堆區分配,大小可在運行時確定,突破了靜態數組必須編譯期定長的限制,但需要程序員手動管理內存的分配與釋放,是理解C++內存模型的關鍵實踐。01創建動態數組通過int*arr=newint[n]分配,n可以是運行時變量(如用戶輸入),返回指向首元素的指針,用法與靜態數組相同。newint[n]02動態二維數組先分配行指針數組,再逐行分配列空間,每行獨立管理,支持不規則行數的靈活結構。int**mat03釋放動態數組必須用delete[]釋放整個數組,釋放后應將指針置為nullptr防止懸空指針被誤用。delete[]04靜態vs動態靜態數組編譯期定長、存于棧區、自動釋放;動態數組運行期定長、存于堆區、手動釋放,適合大數據量或長度不確定的場景。StackvsHeapPREPROCESSOR編譯預處理命令與頭文件管理編譯預處理命令在正式編譯前由預處理器執行文本替換操作,#include實現代碼模塊化復用,#define提供宏替換功能,條件編譯指令防止頭文件重復包含,這些機制是C++項目組織和代碼管理的基礎工具。#include文件包含<…>從標準庫路徑搜索,"…"從當前項目路徑搜索,預處理器將頭文件內容原樣插入替換#include#define宏定義無參宏純文本替換無類型檢查;帶參宏需注意參數加括號,避免優先級歧義#defineIncludeGuard頭文件保護#ifndef/#define/#endif包裹頭文件,防止多次包含導致類或函數重定義編譯錯誤#ifndef/#endif現代C++替代方案const/constexpr替代無參宏,inline函數替代帶參宏,#pragmaonce簡化頭文件保護ModernC++VARIABLESCOPE全局變量與局部變量的對比分析全局變量與局部變量在存儲區域、生命周期、默認初始值和作用域上存在根本差異,理解這些差異對正確使用數組至關重要。全局變量定義在函數外部,存儲在全局/靜態存儲區。程序啟動時分配、結束時釋放,未初始化時默認值為0,作用域覆蓋整個文件。全局/靜態區局部變量定義在函數或代碼塊內部,存儲在棧區。進入作用域時分配、離開時自動釋放,未初始化時值為隨機垃圾值,必須手動賦初值。棧區跨文件共享全局變量可通過extern聲明在其他文件中訪問;若加static修飾(staticintg_num),則作用域限制在當前文件內,防止命名沖突。extern/static數組場景應用大型數組建議定義為全局變量或使用動態分配,避免棧溢出(棧區空間有限,通常幾MB);小型臨時數組用局部變量即可。棧溢出防護CHAPTER05字符數組與字符串處理從C風格字符串到std::string的演進與實踐C/C++FUNDAMENTALS字符數組的定義與C風格字符串字符數組存儲char類型元素,C風格字符串必須以'\0'空字符結尾,實際空間比可見字符數多1。定義方式chars[10]定義可存10個字符的數組;逐個字符初始化時,末尾必須顯式添加終止符'\0'chars[10]常量初始化chars[]="Hello"編譯器自動追加'\0',數組實際大小為6(5字符+1終止符),這是最常用的方式自動追加'\0'終止符作用strlen/strcpy等標準庫函數依賴'\0'判斷字符串結束位置,缺少終止符將導致越界讀取和不可預測行為strlen/strcpy數組vs字符串chars[5]={'a','b','c','d','e'}是字符數組但非字符串——無'\0'則不能整體輸出,會越界讀取無'\0'≠字符串C-StyleStringOperationsC風格字符串的輸入輸出與庫函數C風格字符串通過cstring頭文件提供的庫函數進行操作,這些函數依賴'\0'終止符工作但不進行邊界檢查,使用時必須確保目標緩沖區足夠大,否則將導致緩沖區溢出等嚴重安全隱患。Input輸入方式cin>>s以空白符分隔讀取單詞,無法讀空格;cin.getline(s,n)讀取整行最多n?1個字符并自動加'\0',更安全。Output輸出方式cout<<s從首字符輸出直到遇到'\0',無需逐字符循環;若字符數組缺少'\0'則輸出內容不可控。cstring常用庫函數strlen(s)返回字符數(不含'\0');strcpy/strcat分別用于拷貝與拼接;strcmp(s1,s2)按字典序比較。Warning安全陷阱strcpy和strcat不檢查目標數組容量,src超出dst剩余空間將導致緩沖區溢出,推薦strncpy/strncat限制拷貝長度。C++StandardLibrarystd::string類:現代C++字符串處理std::string是C++標準庫提供的字符串類,封裝了動態內存管理和豐富的操作接口,支持直接賦值、拼接、比較和子串查找,從根本上消除了C風格字符串的'\0'管理和緩沖區溢出問題,是現代C++開發的首選。基本操作直接賦值、s1+s2拼接、s1==s2比較、s.length()獲取長度,無需關心內存分配和'\0'終止符s=s1+s2與C字符串互轉s.c_str()返回constchar*用于調用C庫函數;strings(cstr)從C字符串構造,實現兩種風格無縫銜接c_str()?string豐富接口substr提取子串,find查找位置,replace替換,insert插入,erase刪除——覆蓋字符串操作全場景substr·find·replace性能考量內部采用小字符串優化(SSO),短字符串直接存在棧上;頻繁拼接時建議用reserve()預分配容量減少重分配SSO·reserve()StringComparisonC風格字符串與std::string對比C風格字符串與std::string在內存管理、操作接口、安全性和性能特征上存在顯著差異,std::string在絕大多數場景下更優,但C風格字符串在與CAPI交互和嵌入式資源受限場景中仍有不可替代的價值。對比維度C風格字符串(char[])std::string內存管理手動管理,需預留足夠空間自動管理,動態擴容終止符必須手動維護'\0'內部自動維護,對用戶透明賦值與拼接需用strcpy/strcat函數直接用=和+運算符比較操作需用strcmp()函數直接用==、<、>運算符安全性易緩沖區溢出,無邊界檢查at()方法提供越界檢查適用場景CAPI交互、嵌入式

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯系上傳者。文件的所有權益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
  • 4. 未經權益所有人同意不得將文件中的內容挪作商業或盈利用途。
  • 5. 人人文庫網僅提供信息存儲空間,僅對用戶上傳內容的表現方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
  • 6. 下載文件中如有侵權或不適當內容,請與我們聯系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論