1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142
| 存放地址的变量称为指针变量,简称为指针。 在访问指针变量时,只能看到地址,只有通过这个地址,才能访问地址单元中的内容,这样的访问称为对于内存单元的间接访问。 指针变量定义的格式:<类型名> *变量名1,*变量名2; 指针变量尽管存放的都是地址,但是存在类型上的差别。指针变量的类型就是它所指定的地址单元中存放的数据的类型。 指针变量在声明后,变量的值(地址)是随机的,这样的指针是不安全的,给指针赋为0或者写成NULL,表示空指针,不指向任何内存单元。 指针变量必须初始化后才可以正确使用,初始化就是给它分配一个有效的数据地址。 1、在定义时初始化,char ch1='Y'; char *pch1=&ch1; 2、定义指针后,用赋值的方式初始化, char ch1='Y'; char *pch1=NULL; pch1=&ch1; 间接引用运算符“*”是一种一元运算符,它和指针变量连用,对指针所指向的内存单元进行间接访问。使用格式:*指针变量 指针可以进行加减法,不过和一般的算数运算有不同的含义。指针的加减法表示当前位置前后第n个数据的地址。
cout<<"kl["<<i<<"]"; 输出方式
指针和指针直接相加是没有意义的,也是不允许的,指针和指针相减是可以的,其意义是求出两个指针之间可以存放几个指定类型的数据。 1、不允许用一个整数减一个指针。 2、指针的赋值运算一定是地址的赋值。 3、不同类型的指针是不可以相互赋值的。在为指针赋值时,不存在类型的自动转换机制。 4、两个指针变量相等,表示它们指向相同的内存地址。
动态内存是程序执行时才可以申请、使用和释放的内存,动态内存也称为堆内存。 动态内存不能通过变量名来使用,而只能通过指针来使用。
####C语言动态内存的申请与释放 int *pn=(int *)malloc(sizeof(int)); free(*pn);
####C++动态内存的申请与释放 int *pn=new int(10); 如果申请成功,指针pn就获得一个有效的地址,并且使得*pi=10; delete<*pn>; 申请动态一维数组时,要在new表达式中加上申请数组的大小,其格式为: new<类型名>[表达式]; delete[]<指针名>;
引用是C++中新引入的概念,是C语言中不存在的数据类型。 引用是变量或者其他编程实体(如对象)的别名,因此,引用是不可以单独定义的。 指针变量本身也有自己的地址,是可以独立存在的,而引用是不可以独立存在的。
使用规范:<类型名>&引用名=变量名; 变量名必须是已经定义的,并且和引用的类型相同。 引用必须在声明的同时完成初始化,不可以先声明引用,再用另一个语句对它进行初始化。 注:1、引用不能独立存在,它只是其他变量的别名。 2、引用必须在声明的同时初始化。 3、引用一旦定义,引用关系就不可以更改。如果B是A的引用,就不可能是其他变量的引用。 4、引用的类型就是相关变量的类型,引用的使用和变量的使用相同。 在实际的程序中,没有必要在一个程序作用域中定义一个变量后,又定义它的引用。在程序中真正使用引用的地方是在函数的调用中;或者将引用作为函数的形式参数,或者将引用作为函数的返回值。
用指针作为函数参数实现地址调用,需要满足的条件: 1、函数的形式参数是指针变量。 2、函数的实际参数是内存的地址,具体可以说是数组名、变量的地址、用变量地址初始化的指针。 3、形式参数指针类型和实际参数地址类型必须相同。
******如果需要通过函数调用改变主调函数中变量的值,必须采用地址调用方式。 ******直接的值交换可以改变函数中的交换,但是返回的主调函数中没有完成交换。 使用地址交换示例: void change(int *x , int *y){ int temp = *x; *x = *y; *y = temp; } int a , b; change(&a , &b);
引用作为函数参数 引用的主要作用就是作为函数的形式参数。 特点:1、引用作为形式参数时,实际参数是相同类型的变量。 2、引用作为形式参数时,参数传递属于地址传递。 3、引用作为形式参数时,在函数中并不产生实际参数的副本,形式参数的引用和实际参数的变量实际上是同一个实体。 4、函数对引用的操作,也是对实参变量的操作,函数调用可以改变实际参数的值。 void change(int &a , int &b){ int j =a; a=b; b=j; } int a , b; change(a,b);
两者相较,都是地址调用,都不建立实参的副本,不过指针需要定义指针变量,而引用不用,故而执行效率更高。
1、常指针 常指针就是指向常量的指针。就是规定指针所指向的内容```不可以通过指针的间接引用来改变```,通过其它的方式还是可以改变的。 常指针定义的格式 const <类型名> *<指针名>; 例如:const int *ptint; 指针ptint的类型是(const int *); 2、常引用 常引用使用规范:const <类型名><引用名>&; 3、指针常量 指针常量。也就是指针本身的内容是常量,不可以改变。 使用规范:<类型名>*const<指针名>=<初值>; 数组名就是一个指针常量。 4、指针函数 如果一个函数的返回值是指针,则这样的函数称为指针函数。 例:int *func(int k); 函数返回一个整形数据的指针。返回指针,实际上就是返回一个内存单元的地址。 5、函数指针 指向函数的指针称为函数指针。 使用规范:<类型名>(*指针名)(形参列表); 例:int (*fptr)(int , int); 6、字符串 6.1、C++字符串常量是用双引号括起的字符序列,并以字符'\0'作为结束标志。 6.2、字符串常量存放在内存的常量区域,有自己固定的首地址,这个地址可以看作常指针也可以看作指针常量。 6.3、C++处理字符串有两种方式:数组方式和指针方式 数组方式是将字符串存入字符数组后,再进行处理。 char string_array[]="what is a nice day!"; 指针方式是用字符串常量来初始化一个字符指针。 char *string_pt="what is a nice day!"; 6.4、字符串处理函数,头文件<cstring> 功能 函数原型 返回值 说明 字符串长度 int strlen(const char *string); 长度值 ‘\0’不计入 字符串复制 char *strcpy(char *s1,const char *s2); 复制的字符串 s1要有足够的空间 按字符数复制 char *strncpy(char *s1,const char *s2,int n); 复制的字符串 s1要有足够的空间 字符串比较 int strcmp(const char *s1,const char *s2); >0对应s1>s2,类似 按字符顺序的ASCII码值比较 字符串连接 char *strcat(char *s1,const char *s2); 连接后的字符串 s1要有足够的空间 注:strncpy注意给‘\0’留出位置
####访问数组的方式及注意事项 int A[10],*pa = A 1、数组名和下标 A[0],A[4] 2、指针和下标 pa[0],pa[4] 3、指针加偏移量的间接引用 *(pa+0),*(pa+4) 4、数组名加偏移量的间接引用 *(A+0),*(A+4) 5、指针自加后的间接引用 *pa++ 但是采用这种方式会改变指针本身的值 必要时要对指针重新初始化 注:不允许数组名自加后的间接引用来访问数组元素 *A++ 因为数组名是常数,不可以通过加1进行改变
指针数组 若数组元素是某种类型的指针,称这样的数组为指针数组 使用规范:<类型> *<数组名>[常量表达式] char *member_name[10]={"Merry","John","Hill"}; 访问二维数组的方式:*(*(指针名+i)+j);
####指针与结构体 1、struct student{ long num; char name[20]; float score; }; student stu={20041118,"Lili",81}; student *ps = &stu;
2、使用new操作在堆中给结构指针分配空间 student *ps = new student;
用结构指针访问结构成员时,用箭头操作符替代原来的点操作符
####内存泄漏和指针悬挂 1、内存泄漏是指动态申请的内存空间没有正常的释放 2、指针悬挂是指让指针指向一个已经释放的空间
|