c++ 语言程序设计 第六章 指针、引用和动态空间管理 (第一讲)

98
C++ 语语语语语语 语语语 语语 语语语语语语语语语 语 语语 语语

Upload: ziven

Post on 06-Jan-2016

186 views

Category:

Documents


2 download

DESCRIPTION

C++ 语言程序设计 第六章 指针、引用和动态空间管理 (第一讲). 学习目标. . 掌握定义各种指针的方法,掌握指针的基本操作; 了解指针与数组的关系,掌握利用指针访问数组元素的方法; 了解指针与函数的关系,掌握利用指针传递数据参数和函数参数的方法; 了解引用的概念和定义各种引用的方法,掌握利用引用传递数据参数; 掌握动态空间的申请和释放的方法,会利用指针操纵动态空间。. 第一讲主要内容. 指针的概念 指针变量的定义 常值指针 指针的基本操作. . 指针变量的定义. — 定义格式: 类型修饰符 * 变量名 〖 = 指针表达式 〗;. - PowerPoint PPT Presentation

TRANSCRIPT

Page 1: C++ 语言程序设计 第六章 指针、引用和动态空间管理 (第一讲)

C++ 语言程序设计

第六章指针、引用和动态空间管理(第一讲)

Page 2: C++ 语言程序设计 第六章 指针、引用和动态空间管理 (第一讲)

学习目标1. 掌握定义各种指针的方法,掌握指针的

基本操作;2. 了解指针与数组的关系,掌握利用指针

访问数组元素的方法;3. 了解指针与函数的关系,掌握利用指针

传递数据参数和函数参数的方法;4. 了解引用的概念和定义各种引用的方法,

掌握利用引用传递数据参数;5. 掌握动态空间的申请和释放的方法,会

利用指针操纵动态空间。

Page 3: C++ 语言程序设计 第六章 指针、引用和动态空间管理 (第一讲)

第一讲主要内容

指针的概念 指针变量的定义 常值指针 指针的基本操作

Page 4: C++ 语言程序设计 第六章 指针、引用和动态空间管理 (第一讲)

指针变量的定义 ..— 定义格式:类型修饰符 *变量名〖 =指针表达式 〗 ;

例如:例如:int *pnint *pn,, *ph;*ph;double d,*pd1=&d,*pd2=pd1;double d,*pd1=&d,*pd2=pd1;char *s="This is a string";char *s="This is a string";void *pd3=NULL,*pd4=0;void *pd3=NULL,*pd4=0;long *pd5=NULL; long *pd5=NULL;

Page 5: C++ 语言程序设计 第六章 指针、引用和动态空间管理 (第一讲)

指针变量的定义ddpd1pd1

pd2pd2

ss

This is a string\0This is a string\0

图图 6-26-2 指针图示方法示例指针图示方法示例

pd3pd3

pd4pd4

pd5pd5

Page 6: C++ 语言程序设计 第六章 指针、引用和动态空间管理 (第一讲)

指针的概念空指针:地址值为 0 ,专用于表示未指向任何

数据;地址值 0 可用 NULL 表示;无类型指针( void 指针):无类型限制的指

针,可以用来指向任何类型的数据。

Page 7: C++ 语言程序设计 第六章 指针、引用和动态空间管理 (第一讲)

指针的基本操作 ..• —— 指针赋值:操作符 =

同类型指针之间可以互相赋值任何类型的指针可赋值给 void 指针,但反

过来却不行,例如:char c=’X’,*s; s=&c;void *p1,*p2=NULL;p1=s; // 允许s=p2; // 不允许

Page 8: C++ 语言程序设计 第六章 指针、引用和动态空间管理 (第一讲)

指针的基本操作 ..

—— 取变量的地址:操作符 &例如: int k,*p; p=&k; //p 指向变量 k

上面两个语句可以合并成一个: int k,*p=&k; //p 指向变量 k

Page 9: C++ 语言程序设计 第六章 指针、引用和动态空间管理 (第一讲)

指针的基本操作 ..• —— 间接访问:操作符 *

通过 1 元操作符 * 可以存取指针所指向的数据,例如: int *pd,d; pd=&d; // 使 pd 指向 d *pd=99; cout<<*pd<<' '<<d; 程序输出 99 99

Page 10: C++ 语言程序设计 第六章 指针、引用和动态空间管理 (第一讲)

指针的基本操作 .. * 和 & 是两个互逆的操作,当这两个

操作符碰到一起时,其作用相互抵消,例如 *&k=3与 k=3效果完全相同

Page 11: C++ 语言程序设计 第六章 指针、引用和动态空间管理 (第一讲)

常值指针 ..

— 含义之一:所指向的数据为常值定义这样指针时须将 const 放在 * 号之前,

例如: const char *s="Hello!";

或 char const *s="Hello!";

Page 12: C++ 语言程序设计 第六章 指针、引用和动态空间管理 (第一讲)

常值指针 ..定义这样指针时不必初始化,如:

const char *s; s="Hello!";

s 所指向的数据不可改变,但 s 本身可改变,例如: s="Hi!"; // 正确! *s='Y'; // 错误!

Page 13: C++ 语言程序设计 第六章 指针、引用和动态空间管理 (第一讲)

常值指针 ..• —— 含义之二:指针本身为常值

定义这样指针须将 const 放在变量名之前,而且必须初始化。如: char * const s="Hello!";

s 本身不可改变,但所指向的数据可以改变,例如: s="Hi!"; // 错误! *s='Y'; // 正确!

Page 14: C++ 语言程序设计 第六章 指针、引用和动态空间管理 (第一讲)

常值指针• — 常值也可以是上述两种含义的综合

,如: const char * const s="Hello!";

或 char const * const s="Hello!";

Page 15: C++ 语言程序设计 第六章 指针、引用和动态空间管理 (第一讲)

指针的基本操作 ..• —— 判断一指针是否是空指针:

操作符 == 和 != “ 如果 p 是空指针,则 ...”

if(p==0)...

if(p==NULL)...

if(!p)... // C++ 风格

Page 16: C++ 语言程序设计 第六章 指针、引用和动态空间管理 (第一讲)

指针的基本操作 ..“ 如 果 p 不 是 空 指 针 , 则 ...”

if(p!=0)...

if(p!=NULL)...

if(p)... // C++ 风格 也可利用 > < >= <= 等操作符比较两个指

针的大小,但很少用到。

Page 17: C++ 语言程序设计 第六章 指针、引用和动态空间管理 (第一讲)

指针的基本操作 ..—— 计算两地址间数据单元的个数:操作符 – 同类型的两指针相减,其结果是一个整数,表示两地址之间可容纳的相应类型数据的个数,例如:int n,m[12],*p1=&m[5],*p2=&m[10];n=p2-p1; //n==5

Page 18: C++ 语言程序设计 第六章 指针、引用和动态空间管理 (第一讲)

指针的基本操作 ..

m

11109876543210

p1

p2

Page 19: C++ 语言程序设计 第六章 指针、引用和动态空间管理 (第一讲)

指针的基本操作 ..—— 指针移动:移动 n 个单位格式:

指针表达式 + n 指针变量 += n指针表达式 - n 指针变量 -= n

移动的实际字节数 = n*sizeof( 指针的类型 )

Page 20: C++ 语言程序设计 第六章 指针、引用和动态空间管理 (第一讲)

指针的基本操作 ..• —— 指针移动:移动 1 个单位

格式: ++指针变量 指针变量 ++ --指针变量 指针变量 --执行 int k,*pk=&k; cout<<endl<<++pk; cout<<endl<<pk;显示的是两个相同的地址

Page 21: C++ 语言程序设计 第六章 指针、引用和动态空间管理 (第一讲)

指针的基本操作 ...执行

int k,*pk=&k; cout<<endl<<pk++; cout<<endl<<pk;显示的是两个不同的地址

• —— 指针表达式也有与数值表达式类似的副作用问题

Page 22: C++ 语言程序设计 第六章 指针、引用和动态空间管理 (第一讲)

指针的基本操作 ..操作名称 操作符 第一操作对象 副作用 操作结果

前增 1 ++

变量有

视同变量

前减 1 --

赋值 =

复合赋值 += 、 -= 、 *= 等

后增 1 ++ 视同常量

后减 1 --

取地址 &

无间接访问 *

任意视同变量

其他 + 、 - 、 / 、== 等 视同常量

Page 23: C++ 语言程序设计 第六章 指针、引用和动态空间管理 (第一讲)

指针的基本操作 ..• —— 指针类型的强制转换

格式:( 类型修饰符 *) 指针表达式

举例 :short i=258; //00000001 00000010

char *p=(char *)&i;

cout<<endl<<int(*p)<<int(*(p+1));

输出是: 21

Page 24: C++ 语言程序设计 第六章 指针、引用和动态空间管理 (第一讲)

指针的基本操作 ..—— 正确理解下列组合操作的含义:

*p++

(*p)++

*++p

++*p

Page 25: C++ 语言程序设计 第六章 指针、引用和动态空间管理 (第一讲)

指针的基本操作 ..*p++ :取 p 所指向单元的数据作为表达式的值,然后使 p 指向下一个单元;

执行 *p++ 后:

( *p++ 的值: 3 )

d 3 6 9

p

3 6 9初始状态: d

p

Page 26: C++ 语言程序设计 第六章 指针、引用和动态空间管理 (第一讲)

指针的基本操作 ..(*p)++ :取 p 所指向单元的数据作为表达式的值,然后使该单元的数据值增1 ;

执行 ( *p)++ 后:

( (*p)++ 的值: 3)

d 4 6 9

p

3 6 9初始状态: d

p

Page 27: C++ 语言程序设计 第六章 指针、引用和动态空间管理 (第一讲)

指针的基本操作 ..*++p :使 p 指向下一个单元,然后取该单元的数据作为表达式的值;

执行 * ++ p 后:

( * ++ p 的值: 6)

d 3 6 9

p

3 6 9初始状态: d

p

Page 28: C++ 语言程序设计 第六章 指针、引用和动态空间管理 (第一讲)

指针的基本操作 ..++*p :将 p 所指向单元的数据值增 1并作为表达式的值。

执行 ++ *p 后:

( ++ *p 的值: 4)

d 4 6 9

p

3 6 9初始状态: d

p

Page 29: C++ 语言程序设计 第六章 指针、引用和动态空间管理 (第一讲)

C++ 语言程序设计

第六章指针、引用和动态空间管理(第二讲)

Page 30: C++ 语言程序设计 第六章 指针、引用和动态空间管理 (第一讲)

第二讲主要内容

数组的指针访问方式 关于“指向数组的指针” 字符指针与字符串 指针数组 数组参数

Page 31: C++ 语言程序设计 第六章 指针、引用和动态空间管理 (第一讲)

数组的指针访问方式 ..

—— 一维数组元素的指针访问方式一维数组名是指向该数组首元素的的常值指针 A[i] ←→ *(A+i) A[0] ←→ *(A+0) ←→ *A int s[]={0,1,2,3,4,5},*p=s; cout<< *p << p[1] << *(p+2) << s[3] << p[4] << *(s+5);

Page 32: C++ 语言程序设计 第六章 指针、引用和动态空间管理 (第一讲)

数组的指针访问方式—— 二维数组元素的指针访问方式 一维数组的情况可以推广到二维数组和更多

维的数组:二维数组名是指向该数组首行一维数组的一

根指针 B[i][j] *(B[i]+j) ↓ ↑ A[j] ←→ *(A+j)

因此 : B[i][j] ←→ *(B[i]+j) ←→ *(*(B+i)+j)

Page 33: C++ 语言程序设计 第六章 指针、引用和动态空间管理 (第一讲)

数组的指针访问方式 ..当 i 、 j 之一为 0 或均为 0 时:B[i][0] ←→ *(B[i]+0) ←→ *B[i] ←→ **(B+i)

B[0][j] ←→ (*(B+0))[j] ←→ (*B)[j] ←→ *(*B+j)

B[0][0] ←→ *(B[0]+0) ←→ *B[0] ←→ **(B+0) ←→ **B

Page 34: C++ 语言程序设计 第六章 指针、引用和动态空间管理 (第一讲)

数组的指针访问方式 ..

—— 数组的下标操作就是一种特定形式的指针操作: A[i]是 *(A+i)的另一种表示形式。

Page 35: C++ 语言程序设计 第六章 指针、引用和动态空间管理 (第一讲)

关于“指向数组的指针” ..—— 一维数组的例子:

int s[5];int (*ps1)[5]=&s; int *ps2=s; // 或 =&s[0];

Page 36: C++ 语言程序设计 第六章 指针、引用和动态空间管理 (第一讲)

关于“指向数组的指针” ..

ps1ps1(&s)(&s)

ps2ps2 (s (s 或 或 &s[0])&s[0])

Page 37: C++ 语言程序设计 第六章 指针、引用和动态空间管理 (第一讲)

关于“指向数组的指针” ..

—— 二维数组的例子: int w[3][4];int (*p1)[3][4]=&w; int (*p2)[4]=w; // 或 =&w[0]; int *p3=w[0]; // 或 =&w[0][0];

Page 38: C++ 语言程序设计 第六章 指针、引用和动态空间管理 (第一讲)

关于“指向数组的指针” ..p1

( &w )

p2

( w 或 &w[0] )

p3

( w[0] 或 &w[0][0] )

Page 39: C++ 语言程序设计 第六章 指针、引用和动态空间管理 (第一讲)

关于“指向数组的指针” ..

—— 直接计算数组单元地址二维数组 i 行 j 列单元地址 =

首元素地址+ i× 列数+ j

例 6.1 :设计函数 show_matrix ,它显示参数传来的任意规格的整型二维数组。

Page 40: C++ 语言程序设计 第六章 指针、引用和动态空间管理 (第一讲)

关于“指向数组的指针” .. 1:  #include<iomanip.h> 2:    3:  void show_matrix(int *Array, int row,int col,int width){ …… 7:  for(int i=0;i<row;i++){ 8:  cout<<endl; 9:  for(int j=0;j<col;j++) cout<<setw(width) <<*(Array+i*col+j); 10:  } 11:  }

Page 41: C++ 语言程序设计 第六章 指针、引用和动态空间管理 (第一讲)

关于“指向数组的指针” 12:

13:void main(){ 14:  int s[][3]={{ 1, 2, 3}, { 4, 5, 6}, { 7, 8, 9}, {10,11,12}};

15:  show_matrix(s[0],4,3,5);

16:  cout<<endl;

17: }

也可以是:也可以是:&s[0][0]&s[0][0]

Page 42: C++ 语言程序设计 第六章 指针、引用和动态空间管理 (第一讲)

字符指针与字符串 ..—— 程序中的字符串常量就是指向该字符串的指针,例如: char *p="string";

或 char *p;

P="string";

Page 43: C++ 语言程序设计 第六章 指针、引用和动态空间管理 (第一讲)

字符指针与字符串 ..——(a) char *p="string";

和 (b) char p[]="string";的区别(b) 是p[]={'s','t','r','i','n','g','\0'};

的简略表示形式, (a)没有类似的表示形式

Page 44: C++ 语言程序设计 第六章 指针、引用和动态空间管理 (第一讲)

字符指针与字符串 .. (a)中的字符串存储于静态数据区,( b)中

的字符串的存储特性由相应的变量决定,可以是静态的或自动的

(a)中的字符串一般不应改变

Page 45: C++ 语言程序设计 第六章 指针、引用和动态空间管理 (第一讲)

字符指针与字符串 ..—— 例 6.2 设计函数 STRLEN ,模拟标准函数 strlen 。

int STRLEN(const char *d){ int p=0; while( *d++ ) p++; return p;}

Page 46: C++ 语言程序设计 第六章 指针、引用和动态空间管理 (第一讲)

字符指针与字符串 ..—— 例 6.3 设计函数 STRCAT ,模拟标准函数 strcat 。 char *STRCAT(char *s, const char *d){ char *p=s; while(*p) p++; do *p++=*d; while(*d++); return s;}

Page 47: C++ 语言程序设计 第六章 指针、引用和动态空间管理 (第一讲)

指针数组 ..

—— 若数组的每个元素是一个指针,则称为指针数组,例如:

int *ip[10];double *dp[5][8];

int a,b,c,d;

int *s[]={&a,&b,&c,&d};

Page 48: C++ 语言程序设计 第六章 指针、引用和动态空间管理 (第一讲)

指针数组 ..—— 指针数组应用:构造字符串符号表

例如: char *MONTH[]={

NULL,"January","Feburay",

"March","April","May","June",

"July", "August","September",

"October","November","December"

};

Page 49: C++ 语言程序设计 第六章 指针、引用和动态空间管理 (第一讲)

指针数组 ..—— 指针数组应用:获取命令行参数信息命令行参数实例:C:\>attrib +r readme.txt

主函数形参的含义:int main(int argc,

char *argv[])

命令行参数的个命令行参数的个数(至少是数(至少是 11 ))

存放命令行参数存放命令行参数的“符号表”的“符号表”

Page 50: C++ 语言程序设计 第六章 指针、引用和动态空间管理 (第一讲)

指针数组 .. argv[0] 指向被运行程序的全路径程序文件名。

argv[1] 指向命令行程序名后的第一个字符串。

argv[2] 指向命令行程序名后的第二个字符串。

……argv[argc-1]

指向命令行程序名后的最后一个字符串。argv[argc]

空指针( NULL )。

Page 51: C++ 语言程序设计 第六章 指针、引用和动态空间管理 (第一讲)

指针数组 .. 1:  // 例 6.4 ,文件名 doscomm.cpp: 演示 2:  #include <iostream.h> 3:  #include <stdlib.h> 4:    5:  int main(int argc, char *argv[]){ 6:  int i; 7:  cout<<" 有 "<<argc <<" 个命令行参数: "<<endl<<endl; 8:  for (i=0;i<argc;i++) 9:  cout<<"argv["<<i<<"]: " <<argv[i]<<endl; 10:  return 0; 11:  }

Page 52: C++ 语言程序设计 第六章 指针、引用和动态空间管理 (第一讲)

指针数组 ..—— 指针数组应用:间接排序例 6.5 :设计函数模版

template<class T,int size >void show_in_order(T data[]);

它将数组 data 中的 size 个数据按由小到大的顺序显示输出,但不改变 data 中数据的原有存储顺序。

Page 53: C++ 语言程序设计 第六章 指针、引用和动态空间管理 (第一讲)

指针数组 ..template<class T,int size> void show_in_order(T data[]){ T *pd[size]; int m; for(m=0;m<size;m++) pd[m]=&data[m];   for(m=0;m<size-1;m++){ int j=m; for(int i=m+1;i<size;i++) if(*pd[i]<*pd[j]) j=i; cout<<*pd[j]<<' '; if(j>m) pd[j]=pd[m]; } cout<<*pd[size-1]; }

Page 54: C++ 语言程序设计 第六章 指针、引用和动态空间管理 (第一讲)

指针数组 ..void main() //演示{ int data[]={12,23,9,34,45,7,78,-33,59,3}; #define SIZE (sizeof(data)/sizeof(data[0])) int m; cout<< endl<<"排 序 前: "; for(m=0;m<SIZE;m++) cout<<data[m]<<' '; cout<< endl<<"排序效果: "; show_in_order<int,SIZE>(data); cout<< endl<<"排 序 后: "; for(m=0;m<SIZE;m++) cout<<data[m]<<' ';}

Page 55: C++ 语言程序设计 第六章 指针、引用和动态空间管理 (第一讲)

指针数组如果颠倒两个模板参数的顺序 :template< int size, class T >

void show_in_order(T data[]);

则主函数中的调用show_in_order<int,SIZE>(data);

可改为show_in_order<SIZE>(data);

演示

Page 56: C++ 语言程序设计 第六章 指针、引用和动态空间管理 (第一讲)

数组参数 ..—— 形参表中的数组参数一般不限定第一维的大小,如: int sum(int array[],int size);

和 void sumAll2(int data[][5], int result[],int rows);

Page 57: C++ 语言程序设计 第六章 指针、引用和动态空间管理 (第一讲)

数组参数 ..—— 形参表中的数组参数实际上就是指针参数,因此前例也可说明为: int sum(int *array,int size);

和 void sumAll2(int (*data)[5], int *result,int rows);

Page 58: C++ 语言程序设计 第六章 指针、引用和动态空间管理 (第一讲)

数组参数—— 也即,在形参表中存在着这样的等效关系: A[] ←→ *A 或 (*A) —— 数组参数是指针参数的另一种表示形式。在函数主要以下标方式对参数指针所指向的数据进行操作的情况下,将指针说明为“数组”可使程序更容易理解。

Page 59: C++ 语言程序设计 第六章 指针、引用和动态空间管理 (第一讲)

C++ 语言程序设计

第六章指针、引用和动态空间管理(第三讲)

Page 60: C++ 语言程序设计 第六章 指针、引用和动态空间管理 (第一讲)

第三讲主要内容

指针与函数 引用 动态空间管理

Page 61: C++ 语言程序设计 第六章 指针、引用和动态空间管理 (第一讲)

指针与函数 ..—— 指针参数 作用 1 :通过将数据区的地址传递给函数,使函

数能够改动该地址处的数据,例如:

int addTo(int data,int *agg) { return *agg+=data; }

可以如下方式使用函数:

int total=10; cout << addTo(5,&total);

Page 62: C++ 语言程序设计 第六章 指针、引用和动态空间管理 (第一讲)

指针与函数 ..作用 2 :减少参数传递过程中的数据复制

量如果仅以“作用 2” 为目的,应将参数说明为常值指针,如void show(const int *p,int n){ for(int i=0;i<n;i++) cout << *p++ << ',";}

也可以是也可以是p[i]p[i]

Page 63: C++ 语言程序设计 第六章 指针、引用和动态空间管理 (第一讲)

指针与函数 ..如果参数是指向数组的指针,也可以按数组

方式进行说明,例如:

void show(const int p[],int n){

for(int i=0;i<n;i++)

cout << p[i] << ',";

}

一般不限定第一般不限定第一维大小一维大小

也可以是也可以是*p++*p++

Page 64: C++ 语言程序设计 第六章 指针、引用和动态空间管理 (第一讲)

指针的基本操作 ..例 6.6 :设计函数 char *nextWord(char **pp); 它从一特定位置开始扫描一字符串,返回所遇见的第一个词,即第一个不含空格的连续的字符序列,如字符串 "What is your name?"中就包含了 4 个词。

Page 65: C++ 语言程序设计 第六章 指针、引用和动态空间管理 (第一讲)

指针的基本操作 .. 主函数: void main() { char s[]= "What is your name?", *ps=s; do cout<<nextWord(&ps) <<endl; while(*ps); }

Page 66: C++ 语言程序设计 第六章 指针、引用和动态空间管理 (第一讲)

指针的基本操作 ..main

W h a t i s y o u r n a m ? s

ps

nextWord

W h a t word

pw pp

e

Page 67: C++ 语言程序设计 第六章 指针、引用和动态空间管理 (第一讲)

指针的基本操作char *nextWord(char **pp)

{

static char word[81];

while(**pp==' ')(*pp)++;

char *pw=word;

while(**pp && **pp!=' ') *pw++=*(*pp)++;

*pw='\0';

return word;

}

Page 68: C++ 语言程序设计 第六章 指针、引用和动态空间管理 (第一讲)

指针与函数 ..• —— 指针函数:返回指针值的函数 定义格式:

类型修饰符 *函数名 (形式参数表 )函数体例如:去掉参数字符串 s 的尾部空格char *trim(char *s){ char *p=s+strlen(s)-1; while(p-s>=0 && *p==' ') p--; *(p+1)='\0'; return s;}

Page 69: C++ 语言程序设计 第六章 指针、引用和动态空间管理 (第一讲)

指针与函数 ..函数所返回的指针不能指向返回后即不存在的对象,如:

int *fun(int a,int b){

if(a>b) return &a;

return &b;

}

不要把参数变量和自动变量的地址作为函数的返回值

Page 70: C++ 语言程序设计 第六章 指针、引用和动态空间管理 (第一讲)

指针与函数 ..• —— 函数指针:指向函数的指针

对于函数:类型修饰符 函数名 ( 形式参数表 );

指向该函数的指针应定义为:类型修饰符 (* 变量名 )( 形式参数表 )

〖 = 函数名〗 ;

Page 71: C++ 语言程序设计 第六章 指针、引用和动态空间管理 (第一讲)

指针与函数 ..对于函数:

类型修饰符 *函数名 ( 形式参数表 );

指向该函数的指针应定义为:类型修饰符 *(* 变量名 )( 形式参数表 )

〖 = 函数名〗 ;

Page 72: C++ 语言程序设计 第六章 指针、引用和动态空间管理 (第一讲)

指针与函数 ..• 例如:• int f1(int n){……}• char *f2(int n,char *s){……}• int (*pf1)(int);• pf1=f1;• // 或: int (*pf1)(int)=f1;• char *(*pf2)(int,char *);• pf2=f2; • // 或: char *(*pf2)(int,char *)=f2;

Page 73: C++ 语言程序设计 第六章 指针、引用和动态空间管理 (第一讲)

指针与函数 .. 1:#include<iostream.h> 2: // 例 6.7   3:int add(int a,int b){ return a+b;} 4:    5:void main(){ 6:  int (*p)(int,int); 7:  p=add; 8:  cout<<add(3,5); 9: cout<<(*p)(3,5); 10: cout<<p(3,5); 11: cout<<(*add)(3,5); 12:}

Page 74: C++ 语言程序设计 第六章 指针、引用和动态空间管理 (第一讲)

指针与函数 ..函数指针的主要用途:将一函数作为参数传

递给另一函数,供该函数调用

例:设计计算定积分的函数 integ ,它根据给定的上、下限和精度要求,计算并返回给定函数的定积分值。

Page 75: C++ 语言程序设计 第六章 指针、引用和动态空间管理 (第一讲)

指针与函数 ..n=5 时近似计算

的原理示意

2 4 6-2

2468

101214

0

4

51

2

.

dxx

Page 76: C++ 语言程序设计 第六章 指针、引用和动态空间管理 (第一讲)

指针与函数 ..double integ(double (*f)(double),

double a,double b,int n){

double s=0.0,span;

double gap=(b-a)/n;

for( span=a+gap/2.0;span<b;span+=gap)

s+=gap*f(span);

return s;

}

作为参数,也可以声明为作为参数,也可以声明为double f(double)double f(double)

Page 77: C++ 语言程序设计 第六章 指针、引用和动态空间管理 (第一讲)

指针与函数 ..• double sqr(double x){ return x*x;}• • double cubic(double x) { return x*x*x;}

• • void man()• {• cout<<integ(sqr,2.0,5.0,100);• cout<<endl;• cout<<integ(cubic,2.0,7.5,100);• }

Page 78: C++ 语言程序设计 第六章 指针、引用和动态空间管理 (第一讲)

引用 ...• —— 引用变量

定义一个引用( reference )就是为一个变量、函数等对象规定一个别名。

定义引用变量的一般格式是:类型修饰符 &别名 = 所代表的对象 ;

Page 79: C++ 语言程序设计 第六章 指针、引用和动态空间管理 (第一讲)

引用 .. 例如:int i=0;int &ir=i; ir=2; // 等同于 i=2;int *p=&ir; // 等同于 int *p=&i;

Page 80: C++ 语言程序设计 第六章 指针、引用和动态空间管理 (第一讲)

引用 ..进一步的例子:int a[10],*p=a;

int &ra1=a[6]; //代表 a[6]

int (&ra2)[10]=a; //代表数组 a

int *&rp1=p; //代表指针变量 p

int &rp2=*p;

//代表 p 所指向的那个对象,//即数组元素 a[0]

Page 81: C++ 语言程序设计 第六章 指针、引用和动态空间管理 (第一讲)

引用 ..—— 引用参数形参表中的引用变量的初始化不是在定义时

完成的,而是在调用时完成的:类型修饰符 &形参变量

引用参数具有指针参数类似的作用,但无需进行指针操作;

Page 82: C++ 语言程序设计 第六章 指针、引用和动态空间管理 (第一讲)

引用 ..—— 指针参数与引用参数的比较指针参数例子:template<class T>void swap(T *a,T *b){ T c = *a; *a = *b; *b = c;}调用方式: int x=3,y=5; swap(&x,&y);

Page 83: C++ 语言程序设计 第六章 指针、引用和动态空间管理 (第一讲)

引用 ..引用参数例子:template<class T>

void swap(T &a,T &b){

T c = a;

a = b;

b = c;

}

调用方式: int x=3,y=5;

swap(x,y);

Page 84: C++ 语言程序设计 第六章 指针、引用和动态空间管理 (第一讲)

动态空间管理 ..—— 数据利用内存空间的几种情况静态空间:静态变量所用的空间,在编译时分配,生存期:应用程序运行的整个期间;

自动空间(堆空间):自动变量所用的空间,在运行到定义该变量所在的块时分配,但在编译时即已确定大小,生存期:从定义处开始到块结束处为止;

Page 85: C++ 语言程序设计 第六章 指针、引用和动态空间管理 (第一讲)

动态空间管理 ..栈空间:函数参数和函数返回值所用的空间,

在函数被调用时分配,但在编译时即已确定大小,生存期:函数被调用的整个期间;

动态空间(自由空间):动态数据所用的空间,用 new 申请时分配,生存期:从申请时开始,直到用 delete 释放时为止。

Page 86: C++ 语言程序设计 第六章 指针、引用和动态空间管理 (第一讲)

动态空间管理 ..#include<iostream.h>int a;void show(int n){ static int b; cout<<b<<; b=n; }void main(){ int c=9,*d=new int(8); show(c); show(*d); delete d;} // 数据利用各种内存空间示意

静态空间

静态空间

自动空间

动态空间

栈空间

Page 87: C++ 语言程序设计 第六章 指针、引用和动态空间管理 (第一讲)

动态空间管理 ..—— 何时需要动态空间?编译时无法确定数据的多少编译时无法确定每个数据所需空间的大

小编译时无法确定数据的生存期数据需要复杂的存储结构

Page 88: C++ 语言程序设计 第六章 指针、引用和动态空间管理 (第一讲)

动态空间管理 ..—— 非数组动态空间 申请空间的格式:new 类型说明〖 (表达式 ) 〗

释放空间的格式: delete 指针表达式【 ,指针表达式】 ;

Page 89: C++ 语言程序设计 第六章 指针、引用和动态空间管理 (第一讲)

动态空间管理 ..示例:int *p1,**p2;

p1=new int(5);

p2=new (int *);

*p2=new int(7);

cout<<endl<<*p1<<' '<<**p2;

delete p1,*p2,p2;

Page 90: C++ 语言程序设计 第六章 指针、引用和动态空间管理 (第一讲)

动态空间管理 ..

*p1

**p2*p2

p1

5

p2

7

Page 91: C++ 语言程序设计 第六章 指针、引用和动态空间管理 (第一讲)

动态空间管理 ..必须用一个由足够生存期的指针指向申请到

的动态空间也可以用一个引用来代表申请到的动态空间,

如int &d=*(new int);

delete &d;

Page 92: C++ 语言程序设计 第六章 指针、引用和动态空间管理 (第一讲)

动态空间管理 ..—— 数组动态空间申请空间的格式:new 类型说明 [元素个数 ] new 类型说明 [行数 ][列数 ]

释放空间的格式: delete []指针表达式【 ,[]指针表达式】 ;

Page 93: C++ 语言程序设计 第六章 指针、引用和动态空间管理 (第一讲)

动态空间管理 ..示例:int *ap=new int[10];

double (*Matrix)[20]= new double[20][20];

……

delete []ap,[]Matrix;

Page 94: C++ 语言程序设计 第六章 指针、引用和动态空间管理 (第一讲)

动态空间管理 ..第一维的说明可以是任意表达式,而从第二维开始就必须是常量表达式。例如(假定 m,n 都是变量):

int *p1=new int[n]; // 正确int (*p2)[6]=new int[n][6];// 正确int (*p3)[n]=new int[m][n]; // 错int (*p4)[n]=new int[10][n];// 错

Page 95: C++ 语言程序设计 第六章 指针、引用和动态空间管理 (第一讲)

动态空间管理 ..

—— 动态空间应用实例改进例 6.5中的函数模版:template<class T,int size >

void show_in_order(T data[]);

使得需要排序输出的数组的大小可以在运行时动态确定。

Page 96: C++ 语言程序设计 第六章 指针、引用和动态空间管理 (第一讲)

动态空间管理 template<class T,int size>void show_in_order(T data[]){ T *pd[size]; ……} template<class T>template<class T>

void show_in_order(T data[],void show_in_order(T data[], int size){ int size){ T **pd=new(int *)[size]; T **pd=new(int *)[size]; …… …… delete []pd; delete []pd;}}

Page 97: C++ 语言程序设计 第六章 指针、引用和动态空间管理 (第一讲)

C++ 语言程序设计

第六章讲完再见

Page 98: C++ 语言程序设计 第六章 指针、引用和动态空间管理 (第一讲)