二维数组及其指针基础
編程學習-二維字符串數組的初始化-動態內存分配
動態內存分配
1.堆內存分配 :
C/C++定義了4個內存區間:代碼區,全局變量與靜態變量區,局部變量區即棧區,動態存儲區,即堆
(heap)區或自由存儲區(free store)。
堆的概念:
通常定義變量(或對象),編譯器在編譯時都可以根據該變量(或對象)的類型知道所需內存空間的
大小,從而系統在適當的時候為他們分配確定的存儲空間。這種內存分配稱為靜態存儲分配;
??? 有些操作對象只在程序運行時才能確定,這樣編譯時就無法為他們預定存儲空間,只能在程序運
行時,系統根據運行時的要求進行內存分配,這種方法稱為動態存儲分配。所有動態存儲分配都在堆
區中進行。
當程序運行到需要一個動態分配的變量或對象時,必須向系統申請取得堆中的一塊所需大小的存貯空
間,用于存貯該變量或對象。當不再使用該變量或對象時,也就是它的生命結束時,要顯式釋放它所
占用的存貯空間,這樣系統就能對該堆空間進行再次分配,做到重復使用有限的資源。
2.堆內存的分配與釋放
堆空間申請、釋放的方法:
在C++中,申請和釋放堆中分配的存貯空間,分別使用new和delete的兩個運算符來完成, 指針變量名
=new 類型名(初始化式); delete 指針名;
例如:1、 int *pi=new int(0);
????? 它與下列代碼序列大體等價:
????? 2、int ival=0, *pi=&ival;
區別:pi所指向的變量是由庫操作符new()分配的,位于程序的堆區中,并且該對象未命名。
堆空間申請、釋放說明:
⑴.new運算符返回的是一個指向所分配類型變量(對象)的指針。對所創建的變量或對象,都是通過
該指針來間接操作的,而且動態創建的對象本身沒有名字。
⑵.一般定義變量和對象時要用標識符命名,稱命名對象,而動態的稱無名對象(請注意與棧區中的臨
時對象的區別,兩者完全不同:生命期不同,操作方法不同,臨時變量對程序員是透明的)。
⑶.堆區是不會在分配時做自動初始化的(包括清零),所以必須用初始化式(initializer)來顯式初
始化。new表達式的操作序列如下:從堆區分配對象,然后用括號中的值初始化該對象。
3.堆空間申請、釋放演示:
⑴.用初始化式(initializer)來顯式初始化
int *pi=new int(0);
⑵.當pi生命周期結束時,必須釋放pi所指向的目標:
???????? delete pi;
注意這時釋放了pi所指的目標的內存空間,也就是撤銷了該目標,稱動態內存釋放(dynamic memory
deallocation),但指針pi本身并沒有撤銷,它自己仍然存在,該指針所占內存空間并未釋放。
4. 在堆中建立動態一維數組
①申請數組空間:
指針變量名=new 類型名[下標表達式];
注意:“下標表達式”不是常量表達式,即它的值不必在編譯時確定,可以在運行時確定。
②釋放數組空間:
delete [ ]指向該數組的指針變量名;
注意:方括號非常重要的,如果delete語句中少了方括號,因編譯器認為該指針是指向數組第一個元
素的,會產生回收不徹底的問題(只回收了第一個元素所占空間),加了方括號后就轉化為指向數組
的指針,回收整個數組。delete [ ]的方括號中不需要填數組元素數,系統自知。即使寫了,編譯器
也忽略。
#include <iostream.h>
#include <string.h>
void main(){
???? int n;
???? char *pc;
???? cout<<"請輸入動態數組的元素個數"<<endl;
???? cin>>n; //n在運行時確定,可輸入17
???? pc=new char[n]; //申請17個字符(可裝8個漢字和一個結束符)的內存空間
???? strcpy(pc,“堆內存的動態分配”);//
???? cout<<pc<<endl;
???? delete []pc;//釋放pc所指向的n個字符的內存空間
???? return ; }
5. 動態一維數組的說明
① 變量n在編譯時沒有確定的值,而是在運行中輸入,按運行時所需分配堆空間,這一點是動態分配
的優點,可克服數組“大開小用”的弊端,在表、排序與查找中的算法,若用動態數組,通用性更佳
。一定注意:delete []pc是將n個字符的空間釋放,而用delete pc則只釋放了一個字符的空間;
② 如果有一個char *pc1,令pc1=p,同樣可用delete [] pc1來釋放該空間。盡管C++不對數組作邊
界檢查,但在堆空間分配時,對數組分配空間大小是紀錄在案的。
③ 沒有初始化式(initializer),不可對數組初始化。
6.指針數組和數組指針
指針類型:
(1)int *ptr;//指針所指向的類型是int?
(2)char *ptr;//指針所指向的的類型是char?
(3)int **ptr;//指針所指向的的類型是int* (也就是一個int * 型指針)?
(4)int (*ptr)[3];//指針所指向的的類型是int()[3] //二維指針的聲明
指針數組:
一個數組里存放的都是同一個類型的指針,通常我們把他叫做指針數組。
比如 int * a[2];它里邊放了2個int * 型變量 .(指針數組)
int * a[2];?
a[0]= new int[3];?
a[1]=new int[3];?
delete a[0];?
delete a[1];
注意這里 是一個數組,不能delete [] ;
數組指針:
一個指向一維或者多維數組的指針.
int * b=new int[10]; 指向一維數組的指針b ;?
注意,這個時候釋放空間一定要delete [] ,否則會造成內存泄露, b 就成為了空懸指針
int (*b2)[10]=new int[10][10]; 注意,這里的b2指向了一個二維int型數組的首地址.?
注意:在這里,b2等效于二維數組名,但沒有指出其邊界,即最高維的元素數量,但是它的最低維數
的元素數量必須要指定!就像指向字符的指針,即等效一個字符串,不要把指向字符的指針說成指向
字符串的指針。
int(*b3) [30] [20]; //三級指針――>指向三維數組的指針;?
int (*b2) [20];???? //二級指針;――>指向二維數組的指針;?
b3=new int [1] [20] [30];?
b2=new int [30] [20];?
刪除這兩個動態數組可用下式:?
delete [] b3; //刪除(釋放)三維數組;?
delete [] b2; //刪除(釋放)二維數組; 在堆中建立動態多維數組
new 類型名[下標表達式1] [下標表達式2]……;
例如:建立loat (*cp)[30][20] ; //指向一個30行20列數組的指針,指向二維數組的指針
cp=new float [15] [30] [20];??? //建立由15個30*20數組組成的數組;
注意:cp等效于三維數組名,但沒有指出其邊界,即最高維的元素數量,就像指向字符的指針即等效
一個字符串,不要把指向字符的指針,說成指向字符串的指針。這與數組的嵌套定義相一致。
?? 總結如下方法:
指針對應關系為
char *a[6]<=>char **a????? //在函數傳遞參數時候很容易出錯
char a[5][6]<=>char (*a)[6]
int a[50][100];
int *p=&a[0][0];?
a[i][j]<=>*(p+100*i+j);
或:
int (*p)[100];???
p=a;
a[i][i]<=>*(*(p+i)+j);
char *a[10];?????? //指針數組
for (i=0;i<10;i++)?
a[i]=new char[10];
for(i=0;i<10;i++)
delete [] a[i];
#include <iostream.h>
#include <stdlib.h>
int main()
{
int (*p)[3];
p= new int [2][3];
int i,j;
for(i=0;i<2;i++)
for(j=0;j<3;j++)
??? p[i][j]=rand()%100;
for(i=0;i<2;i++)
?? {?
??? cout<<endl;
??? for(j=0;j<3;j++)
????? cout<<p[i][j]<<ends;
?? }
?? delete [] p;
return 0;
}
#include<iostream.h>
#include<stdlib.h>
int main()
{
char **a;???????????????? //或者用上面的指針數組的方法也可以
a=new char *[2];
for(int i=0;i<2;i++)
?? a[i]=new char [10];
for(i=0;i<2;i++)
cin.getline(a[i],9);
for(i=0;i<2;i++)
?? cout<<a[i]<<endl;
???
for(i=0;i<2;i++)
?? delete [] a[i];
delete [] a;??????? //不要忘了
a=NULL;
return 0;
}
總結
以上是生活随笔為你收集整理的二维数组及其指针基础的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: C语言中,当计算字符数组长度时,用siz
- 下一篇: Sort详解