第一章程序基礎第六節(jié)指針_第1頁
第一章程序基礎第六節(jié)指針_第2頁
第一章程序基礎第六節(jié)指針_第3頁
第一章程序基礎第六節(jié)指針_第4頁
第一章程序基礎第六節(jié)指針_第5頁
已閱讀5頁,還剩23頁未讀 繼續(xù)免費閱讀

下載本文檔

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

文檔簡介

指針與內存指針如何創(chuàng)建動態(tài)內存。指針如何釋放所創(chuàng)建的動態(tài)內存野指針的處理辦法。熟練的掌握指針如何創(chuàng)建動態(tài)內存和釋放所創(chuàng)建的動態(tài)內存,熟練的掌握野指針的處理辦法。1在C++程序中,一些變量在整個程序中都是可見的,稱為全局變量。一些只能在一個函數中可知,稱為局部變量。1.6.9指針與程序內存2一個程序將操作系統(tǒng)分配給其運行的內存塊分為4個區(qū)域:1)代碼區(qū),存放系統(tǒng)的代碼,即程序中的各個函數代碼塊。2)全局數據區(qū),存放程序的全局數據和靜態(tài)數據。內存在程序編譯的時候就已經分配好,這塊內存在程序的整個運行期間都存在。在C/C++程序中,不管是局部變量,全局變量、或是動態(tài)變量,在內存中都占用一定的空間,但是它們占用不同的空間。1.6.9指針與程序內存33)堆區(qū),存放程序的動態(tài)數據。程序在運行的時候用new申請任意多的內存,程序員自己負責在何時用delete釋放內存。4)棧區(qū),存放程序的局部數據,即各個函數中的數據。在執(zhí)行函數時,函數內局部變量的存儲單元都可以在棧上創(chuàng)建,函數執(zhí)行結束時這些存儲單元自動被釋放。1.6.9指針與程序內存4在C++中,申請和釋放堆中分配的存貯空間,分別使用new和delete的兩個運算符來完成:申請內存使用new:例如:1、int*pi=newint(0);

它與下列代碼序列大體等價:

2、intival=0,*pi=&ival;區(qū)別:pi所指向的變量是由庫操作符new()分配的,位于程序的堆區(qū)中,并且該對象未命名。指針變量名=new類型名(初始化式);1.6.10指針與動態(tài)內存5new運算符返回的是一個指向所分配類型變量(對象)的指針。對所創(chuàng)建的變量或對象,都是通過該指針來間接操作的,而動態(tài)創(chuàng)建的對象本身沒有名字。例如以下代碼:int*pi=newint(12);其中pi為這個指針的名稱,而12這個整型并沒對象,pi保存了12所在的內存的內存地址。1.6.10指針與動態(tài)內存6在堆中建立動態(tài)一維數組原型如下:注意:“下標表達式”不是常量表達式,即它的值不必在編譯時確定,可以在運行時確定。指針變量名=new類型名[下標表達式];例如以下代碼:intival=10;int*pi=newint[ival];1.6.10指針與動態(tài)內存7在代碼欄編寫以下代碼,編譯并查看輸出:#include<iostream>usingnamespacestd;voidmain(){intn;char*pc;cout<<"請輸入動態(tài)數組的元素個數"<<endl;cin>>n;pc=newchar[n];strcpy(pc,"veryGood");cout<<pc<<endl;delete[]pc;system(“pause”);}1.6.10指針與動態(tài)內存8在堆中釋放指針所創(chuàng)建的內存原型如下:堆空間申請、釋放演示:⑴.用初始化式(initializer)來顯式初始化int*pi=newint(0);⑵.當pi生命周期結束時,必須釋放pi所指向的目標:deletepi;delete指針變量名;注意這時釋放了pi所指的目標的內存空間,也就是撤銷了該目標,稱動態(tài)內存釋放(dynamicmemorydeallocation),但指針pi本身并沒有撤銷,它自己仍然存在,該指針所占內存空間并未釋放,需要注意的是任何類型指針的都會占用四個字節(jié)的內存。1.6.10指針與動態(tài)內存9特別需要注意的是,如果該指針又指向了別處,那么在釋放以前務必要保證指針從新指回原來的內存地址:例如以下代碼,運行時程序會奔潰:#include<iostream>usingnamespacestd;voidmain(){ int*pi=newint(9); intival=5; pi=&ival; deletepi; system(“pause”);}1.6.10指針與動態(tài)內存10在堆中釋放指針所創(chuàng)建的數組內存原型如下:注意:方括號非常重要的,如果delete語句中少了方括號,因編譯器認為該指針是指向數組第一個元素的,會產生回收不徹底的問題(只回收了第一個元素所占空間),加了方括號后就轉化為指向數組的指針,回收整個數組。delete[]的方括號中不需要填數組元素數,系統(tǒng)自知。即使寫了,編譯器也忽略。delete[]指向該數組的指針變量名1.6.10指針與動態(tài)內存11如果指向數組的指針移動了,或者指向了別的內存地址,那么在釋放前務必要將該指針回歸原位,最快捷的辦法是做原始內存地址的備份。例如以下代碼,演示了如何做原始內存地址的備份:#include<iostream>usingnamespacestd;voidmain(){ int*pi=newint[10]; int*temp=pi; intival=20; pi=&ival; pi=temp; delete[]pi; system(“pause”);}1.6.10指針與動態(tài)內存12編譯器不能自動發(fā)現內存錯誤,通常是在程序運行時才能捕捉到。常見的內存錯誤及對策:1)內存分配未成功,卻使用了它。int*pB;*pB=10;解決辦法:在使用內存之前檢查指針是否為NULL。assert(p!=NULL)if(p==NULL)或if(p!=NULL)1.6.10指針與動態(tài)內存132)內存分配雖然成功,但是尚未初始化就引用它。解決辦法:無論用何種方式創(chuàng)建數組,都別忘了賦初值,即便是賦零值也不可省略。例如以下代碼:#include<iostream>usingnamespacestd;voidmain(){ int*pi=newint[10]; for(inti=0;i<10;i++) cout<<pi[i]<<endl; system(“pause”);}1.6.10指針與動態(tài)內存143)內存分配成功并且已經初始化,但操作越過了內存的邊界。charstrText[8];sprintf(strText,"Thisisalongtext!");解決辦法:留心數組的大小,避免數組操作越界。1.6.10指針與動態(tài)內存155)釋放了內存卻繼續(xù)使用它程序中的對象調用關系過于復雜,實在難以弄清楚某個對象是否已經釋放了內存。解決辦法:應該重新設計數據結構,從根本上解決對象管理的混亂局面。4)忘記了釋放內存,造成內存泄露。含有這種錯誤的函數每被調用一次就丟失一塊內存。解決辦法:動態(tài)內存的申請與釋放必須配對,程序中new與delete的使用次數一定要相同,否則肯定有錯誤。1.6.10指針與動態(tài)內存16使用delete釋放了內存后,沒有將指針設置為NULL。導致產生“野指針”?!耙爸羔槨辈皇荖ULL指針,是指向“垃圾”內存的指針。char*pStrBuffer=newchar[256];delete[]pStrBuffer;*pStrBuffer=NULL;1.6.10指針與動態(tài)內存17內存操作注意事項:1)用new申請內存之后,應該立即檢查指針值是否為NULL。防止使用指針值為NULL的內存。2)不要忘記為數組和動態(tài)內存賦初值。防止將未被初始化的內存作為右值使用。3)避免數組或指針的下標越界,特別要當心發(fā)生“多1”或者“少1”操作。4)動態(tài)內存的申請與釋放必須配對,防止內存泄漏。5)用delete釋放了內存之后,立即將指針設置為NULL,防止產生“野指針”。1.6.10指針與動態(tài)內存18指針變量自身也有自己的內存,由于只需要保持一個內存地址,所以任何類型的指針大小都是四個字節(jié)。在代碼欄編寫以下代碼,編譯并查看輸出:#include<iostream>usingnamespacestd;voidmain(){ char*pc; int*pi; short*ps; double*pd; cout<<sizeof(pc)<<endl; cout<<sizeof(pi)<<endl; cout<<sizeof(ps)<<endl; cout<<sizeof(pd)<<endl; system(“pause”);}1.6.11指針的內存地址19如果要保存指針的內存地址,則需要使用到二級指針。在代碼欄編寫以下代碼,編譯并查看輸出:#include<iostream>usingnamespacestd;voidmain(){ intival=10; int*pi=&ival; int**ppi=π cout<<&pi<<endl; cout<<ppi<<endl; system(“pause”);}1.6.11指針的內存地址20void類型的指針可以保存任何類型數據的內存地址,只不過在訪問數據或者修改數據的時候,需要將指針類型轉換為所保存的數據類型。在代碼欄編寫以下代碼,編譯并查看輸出:#include<iostream>usingnamespacestd;voidmain(){ intival=10; int*pi=&ival; void*pv=&ival; cout<<pi<<endl; cout<<pv<<endl; cout<<*(int*)pv<<endl; system(“pause”);}1.6.12void類型的指針21在32位機器中整型與指針都占4個字節(jié),內存的表現方式也都是二進制整數,但是整型和指針所表示的數據類型不同。在代碼欄編寫以下代碼,編譯并查看輸出,可以看到一個編譯錯誤,無法從整型轉換為整型的指針:#include<iostream>#include<windows.h>usingnamespacestd;voidmain(){ intival=0x18ff28; int*pi=ival; system(“pause”);}1.6.12void類型的指針22但是整型類型被強制轉換為整型指針類型后,也可以給指針賦值,這個時候要注意的是指針保存的并不是整型數據所在的內存地址。在代碼欄編寫以下代碼,編譯并查看輸出:#include<iostream>#include<windows.h>usingnamespacestd;voidmain(){ intival=0x18ff00; int*pi=(int*)ival; cout<<pi<<endl; cout<<*pi<<endl; cout<<&ival<<endl; system(“pause”);}1.6.12void類型的指針23本節(jié)介紹了如何使用指針創(chuàng)建動態(tài)內存的辦法,以及如何釋放動態(tài)內存和野指針的處理辦法。運行int*pi=new

int(9);inti

溫馨提示

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

評論

0/150

提交評論