当前位置:文档之家› 第4章 指针和引用

第4章 指针和引用


4.4 指针和const
• 第2章中介绍了const常量,用const修饰符声明的 程序实体具有只读性。声明一个指针时,通过在 声明语句的不同位置使用const可达到3个目的: • 禁止对指针赋值。 • 禁止通过间接引用(*指针)对指针所指的变量赋 值。 • 既禁止对指针赋值,又禁止通过间接引用(*指针) 对指针所指的变量赋值。
• •
4.1.1 声明一个指针变量
• 指针是一种数据类型,基于该类型声明的变量称为指针变 量,该变量存放的是内存中的某个地址,和普通的变量一 样,在使用指针变量之前应先对指针变量进行声明: • 类型*指针变量名;//如 int* pNum; • “*”表示语句声明的是一个指针变量,类型指定了指针所指 的内存单元的数据类型。 • 可以将int*理解成一种符合类型,是指向int型数据的指针。 • 应当注意,下面的语句: • int* pNum1,pNum2; • 声明了一个指针(pNum1)和一个int型变量(pNum2),在 一次性声明多个指针时,每个指针变量名前都要加*, “int *pNum1,*pNum2;”便一次性声明了两个指针变量。
4.4.3 既禁止改写指针,又禁止改写间接引用 • 将上述两种用法结合起来,便可以将所声明的指 针设定为“既禁止改写指针,又禁止改写间接引 用”,如: • int x=5; • const int* const pInt=&x; • 上述代码声明了一个常指针pInt,程序运行过程 中,其值是恒定的,无法修改,同时,无法通过 间接引用的方式改写pInt所指的内存区域。 • 这种情况下,不要忘记指针的初始化。
• C++允许使用C标准库函数中的malloc()和free()函数申请 和释放动态内存,保留这两个函数主要有以下几点考虑: • C++程序经常要调用写好的C函数,而在C语言中,只能使用 malloc()和free()函数。 • 如果C++程序要运行在C语言环境下,必须使用malloc()和 free()函数。 • new和delete的功能是通过调用malloc()和free()来实现的。 • 区别:malloc()和free()是C标准库函数,而new和delete 是C++的运算符。 • malloc()函数的基本调用格式为: • void *malloc( unsigned int size ); • 举例来说,下列语句用于申请一段长度为len,数据类型为 short的动态内存: • short* p=(short*) malloc( len * sizeof(short) );
4.1.2 初始化指针变量
• 声明指针变量时,C++并不会自动对其进行初始化,这时, 指针变量的值是随机的,在内存中乱指一气,此时,通过 指针间接访问所指的内存区域是十分危险的,因为你完全 不知道自己在做些什么。通过取地址符(&)给指针变量赋 值是个有效的手段,实际上,可以在声明一个指针变量的 同时完成其初始化。 • int num=1; • int* pN=# • 上述语句声明了一个指向int型变量的指针pN,并用num在 内存中的地址对其赋值。 • 在使用对指针使用间接引用符前,一定要对其进行初始化 (在声明的同时初始化或赋值),使其有一个确定合适的 值,对于无处可指的指针变量,也要将其初始化为NULL (即0,空指针)。
• C++常常把地址当成整数来处理,但这并不意味着 程序员可以对地址(指针)进行各种算术操作, 事实上,指针所能做的操作是十分有限的,像指 针与其他变量的乘除、两个指针间的乘除、两个 指针相加都是没有意义、不被编译器接受的。合 法的运算具体包括以下几种:指针与整数的加减 (包括指针的自增和自减)、同类型指针间的比 较、同类型的两指针相减。
第4章 指针和引用
• 指针和引用是C++中两个重要的复合数据类型,使 用范围十分广泛,若使用得当,它们就是程序员 手中的神兵利器,但如果程序员对其理解肤浅, 胡乱应用,只会让事情一团糟,本章将带领您一 步步学会使用指针和引用。
4.1 指针的定义与使用
• 根据前面的学习,我们知道:内存是按字节排列的存储空间,每 个字节有一个编号,称为“地址”,程序中用到的数据和声明的 变量就存放在这一个个的字节中,不同类型的数据和变量占用的 字节数不同,如short型变量占用2个内存字节,习惯上将某个变 量占用的几个字节称为内存单元,内存单元占用的字节数随其存 储变量的不同而不同。 通过变量名可以访问该变量对应的内存单元,实际上,我们还可 以直接通过地址来访问某个内存单元,为形象地说明这个问题, 请看下面这个比喻: 假设我们要去A公司给B经理送信,我们有两种方法,一是告诉传 达室人员,这封信要送给B经理,由传达室人员转送,二是知道B 经理在C楼D层E房间,通过这个地址直接将信送给B经理,将内存 比作A公司,B经理就是某个变量,C楼D层E房间是变量占据的内存 空间的地址,传达室人员可以理解为编译器,在程序中,我们可 以直接通过名字访问某个变量,但这实际上是借助了编译器的帮 助,编译器维护了一个变量名和地址的映射表,同时,如果知道 了某个变量内存单元的地址,我们就可以直接对这块内存进行访 问,为了存储地址信息,C++提供了指针这个符合数据类型。
4.3.4 不要使用或释放已经释放的内存块
• 使用或释放已经释放了的内存块会带来意想不到的错误, 在使用delete释放内存时,delete后的指针并不要求一定 是用new命令赋值的那个指针,编译器关心的是内存块的地 址,而不是用哪个指针来释放,见代码4-6。
4.3.5 使用malloc和free动态申请内存
4.5 指针与数组
• C++中,数组和指针的关系十分密切,两者的内部 处理方式几乎是等价的。访问数组中的元素有下 标和指针两种形式,两者是通过前面介绍的指针 算术机制对应的。
4.2.1 指针与整数的加减
• 指针与整数相加减,表示指针在内存空间中向下或向上移动整数个单位,该单位是多 少个内存字节取决于指针所指变量的类型,short型指针每次移动2个字节,double型 指针每次移动8个字节。 将指针变量增加1,其增加的值等于指向的类型占用的内存字节数。 图4.4是指针与整数相加减时指针移动的示意图,对指针变量进行加N运算时: 指针变量新值=指针变量当前值 + N*指针所指类型占用的内存字节数
4.3.1 使用new动态分配内存
• new是一个单目运算符,操作数为一个类型名,返回值为指 向操作数类型的指针。为一个变量分配动态的内存的基本 格式为: • 类型名* 指针变量名 = new 类型名; • 其中的“new 类型名”通知编译器:需要开辟的内存是用 来存储的值是什么类型,new操作符能根据这个类型名自动 计算要分配的存储空间的大小。 • int* pNum = new int; • 举例来说,上述代码会在运行时为一个int型数值分配内存, 声明了指向int型的指针pNum,pNum初始为可以用动态申请 内存的首地址,因此,用指针pNum可访问这块内存区域。 • 申请内存的同时可对该区域进行初始化,对基本的变量类 型,下列语句是合法的: • int* pNum = new int(8);
4.3.3 使用new申请动态数组
• 第3章讨论了通过声明建立数组的方法,实际上, 可以通过new[ ]命令动态创建数组,其基本格式 为: • 类型名* 指针变量名= new 类型名 [ 元素个数 ]; • 上述语句通知编译器动态开辟足以存储“元素个 数”个类型为“类型名”的元素的连续内存空间 (数组),并声明“指针变量名”,指向数组的 第一个元素。 • 和通过声明建立数组不同,使用new申请动态数组 时,元素个数可以是变量,如: • int i=5 • int* p=new int [ i ]; //合法
4.3.2 使用delete动态释放动态申请的内存
• 动态申请的内存,在使用完毕后,应及时将其归还系统, 以供其他程序使用,这项工作必须由程序员来完成, delete语句的使用格式是: • delete 指针; • 其中的指针指向使用new动态申请的内存块,delete指令会 释放动态申请的内存块,但不会删除指针本身,还可以将 指针重新指向另一块内存区域。 • delete语句不能释放声明变量获得的内存,如下述语句是 错误的。 • int x=3; • int* p=&x; • delete p; //错误
4.1.3 指向指针的指针
• 指针变量也是变量,占据一定的内存空间,有地 址,因此可以用一个指针指向它,这称为指向指 针的指针,或二级指针。可已通过“**”声明一 个二级指针,如 • double num; • double* pN=# • double** ppN=&pN; • 上面的指针可以看成指向double*变量类型的指针, 若有需要,还可以定义三级、甚至更高级的指针。
4.4.1
禁止改写指针(常量指针或常指针)
• 在声明一个指针时,如果在*的右边加const修饰符,所声 明的指针称为常量指针(常指针),编译器不允许程序改 写指针的值,换言之,该指针恒指向某个内存地址,如: • int x=0; • int* const pInt=&x; • 上述代码声明了一个指向int型变量的常指针pInt,并用 int型变量x的地址为其初始化,在整个程序的执行过程中, pInt的值无法改变,也就是说,无法让pInt指向别的内存 单元。无法改写pInt并不意味着无法通过间接引用改写 pInt指向的变量,下述代码都是合法的: • x=5; • *pInt=6;
4.1.4 指针赋值
• C++允许同类型的指针间的赋值,如图4.2所示, pN1和pN2是两个相同类型的指针,执行 “pN2=pN1;”这样一个赋值操作后,pN1和pN2指向 同样的地址,也就是说,两个指针指向同一个内 存单元,对*pN2的任何改动都会影响*pN1的值, 反之亦然。
相关主题