260 likes | 387 Views
第六章 指针和引用. 课程 要求. 参考 书目. 课程 内容. 课程 练习. 课程内容. 动态分配内存空间. 面向对象程序设计. 引用. 其他类型指针. 类型定义. 简单链表及应用. 课程要求. 参考书目. 返回首页. 6.5 动态分配内存空间 *. new 运算符可以为所创建的指针变量动态地分配存储空间,而运算符 delete 则用于释放动态分配的存储空间。 使用 new 运算符的一般格式为: < 指针变量 >=new < 类型 > 《 ( 初始值 ) 》 ; < 指针变量 >=new < 类型 >[< 表达式 >];
E N D
第六章 指针和引用 课程 要求 参考 书目 课程 内容 课程 练习
课程内容 动态分配内存空间 面向对象程序设计 引用 其他类型指针 类型定义 简单链表及应用 课程要求 参考书目 返回首页 面向对象程序设计
6.5 动态分配内存空间 * • new运算符可以为所创建的指针变量动态地分配存储空间,而运算符delete则用于释放动态分配的存储空间。 • 使用new运算符的一般格式为: • <指针变量>=new <类型>《(初始值)》; • <指针变量>=new <类型>[<表达式>]; • 对于上述两种情形,如果动态分配不成功,则new运算符返回NULL(0);如果成功分配,则new运算符返回所分配的存储空间的首地址,并将该地址赋给<指针变量>。 prev next back 面向对象程序设计
6.5 动态分配内存空间 * • 使用delete的一般格式为: • delete <指针变量>; • delete [《<表达式>》]<指针变量>; • 第一种格式为将动态分配给<指针变量>的内存空间归还给系统,第二种格式为将动态分配给<指针变量>的数组空间归还给系统。 • 注意,在用new运算符为某个指针变量所指向的数据动态分配存储空间之后,必须用delete运算符撤消,否则该存储空间将一直被占用,直到关闭电脑。 • 例6.30 例6.31 prev next back 面向对象程序设计
6.5 动态分配内存空间 * • 在使用new和delete运算符时,要注意如下几点: • (1) new运算符实际上是为指针变量指定一个确定的值,即用动态的方式指定一个地址给指针变量。 • (2) 如果new运算符动态分配内存失败(内存中没有符合要求的空闲的连续内存单元),则返回NULL(0),此时指针为空指针。此时,要进行空指针判断处理。 • (3) 与数组一样,动态分配存放数组的内存空间时,也不能在分配空间的同时进行初始化。 prev next back 面向对象程序设计
6.5 动态分配内存空间 * • 在使用new和delete运算符时,要注意如下几点: • (4) 可以用new运算符动态分配多维数组空间,但要注意的是,它返回的是行指针。当撤消动态分配二维数组空间时,一定要指明数组的行数,否则只能撤消第0行的内存空间, • (5) 用运算符new动态分配内存空间的指针必须保护起来,直到将该存储空间撤消,否则不仅会带来资源浪费,而且会引起一些意想不到的错误。 prev next back 面向对象程序设计
6.6 引用 * • 6.6.1 引用类型变量的定义和使用 • 引用是另一个变量别名,或另一个变量的同义词,引用变量依附于另一个变量而定义。定义引用类型变量的一般格式为: • <类型> &<变量名1>=<变量名2>; • 其中<变量名1>为引用类型的变量,而<变量名2>必须是已经定义过的且与引变量同类型的变量。 prev next back 面向对象程序设计
6.6 引用 * • 6.6.1 引用类型变量的定义和使用 • 在定义一个引用变量时,编译系统并不会为其单独分配存储空间,因此必须对它进行初始化,将它与某个已定义的同类型的变量相关联。 • 【例6.32】 • 6.6.2 引用和函数 • 1. 引用类型的参数 • 当函数的形参为引用类型时,调用该函数的方式称为引用传递。 prev next back 面向对象程序设计
6.6 引用 * • 6.6.2 引用和函数 • 1. 引用类型的参数 • 用传递具有某些与地址传递相似的特征,即引用类型的参数既可以作为输入参数,也可以作为输出参数。 • 在调用引用类型参数的函数时,对引用类型的参数的操作实际上就是对传递给它的实参的操作,而不需要将实参拷贝一个副本给形参。因为从程序的执行效率上看,引用作为参数,在运行过程中可以节省资源。通常将占用存储空间较大的类型的形参设置为引用类型。 prev next back 面向对象程序设计
6.6 引用 * • 6.6.2 引用和函数 • 2. 引用返回类型 • 函数的返回值也可以是引用类型,此时该函数的返回值一定是某个变量的引用。 • 当函数的返回值为引用类型时,其函数体中的return语句的参数必须为全局变量、静态变量或形参(如果形参为指针类型或引用类型的话),不能为局部变量。 • 【例6.35】 prev next back 面向对象程序设计
6.7 其它类型的指针 * • 6.7.1 void指针 • void指针是空类型的指针,也称为无类型指针,它不指向任何类型,仅仅是一个地址。因此void指针不能进行指针运算,也不能直接取其指针所指向的数据的值。 • 只有将void指针与其它类型的指针相关联,才能使用它。可以将其它类型的指针赋给void指针,但当将void指针赋给其它类型的指针时,必须进行强制类型转换。 • 【例6.36】 【例6.37】 prev next back 面向对象程序设计
6.7 其它类型的指针 * • 6.7.2 const类型指针 • 1. 指向常量的指针 • 指向常量的指针是指指针所指向的数据为常量,定义这类指针的一般格式为: • <类型> const *<指针变量>; • const <类型> *<指针变量>; • 指向常量的指针常用作函数的参数,此时,在函数体中不能改变该指针所指向的数据的值。 • 【例6.38】 prev next back 面向对象程序设计
6.7 其它类型的指针 * • 6.7.2 const类型指针 • 2. 常量指针 • 常量指针是指指针变量的值为常量,定义常量指针的一般格式为: • <类型> * const <指针变量>; • 注意,在定义常量指针时一定要对其初始化。 • 定义指向常量的常量指针的一般格式为: • <类型> const * const<指针变量>; • const <类型> * const <指针变量>; prev next back 面向对象程序设计
6.7 其它类型的指针 * • 3. 指向常量的常量指针 prev next back 面向对象程序设计
6.8 类型定义 * • 所谓类型定义就是利用关键字typedef定义新的类型名,从而可以用该类型名来代替已定义的类型名。类型定义的一般格式为: • typedef <类型> <新类型名1>《,<新类型名2>, …》; • 对于一个已定义的类型,可按如下的步骤定义与它等价的新的类型名: • (1) 写出已定义类型的变量说明; • (2) 将变量名换成新的类型名; prev next back 面向对象程序设计
6.8 类型定义 * • 对于一个已定义的类型,可按如下的步骤定义与它等价的新的类型名: • (3) 在变量说明的前面加上关键字typedef; • (4)这样在第一步中的变量名就是新的类型名。 • 要注意以下问题: • 1. 用typedef定义的是新的类型名,而不是变量,因此编译系统不会为该类型名分配内存空间。 prev next back 面向对象程序设计
6.8 类型定义 * • 要注意以下问题: • 2. typedef只能对已定义的类型建立新的类型名,它不能创建新的类型。 • 3. 使用类型定义的目的是使某些特殊作用的类型从其类型名上可以理解其含义,从而增加程序的可读性,另外还可使程序变得简单、灵活。 prev next back 面向对象程序设计
6.9 简单链表及其应用 * • 链表是指将一组同类型数据(通常为结构体类型)按其特有的方式连接在一起的一种数据结构。 • 链表中的元素称为结点。每一个结点都包含两类数据:一类数据称为结点的值域,它是描述该结点所包含的实际数据,可以由多个不同类型的数据构成;另一类数据称为链域,它用来存储与本结点相邻的结点的地址,其作用是将各个结点连接在一起,它通常是与结点同类型的指针。 prev next back 面向对象程序设计
6.9 简单链表及其应用 * • 任何一个链表都一个起始结点,称为该链表的头结点(head)。 • 链表的最后一个结点称为尾结点,它的next指针不指向任何结点,通常将它设置为空指针。 • 也可以从尾结点开始遍历所有的结点,此时在每个结点中必须有一个指向上一个结点指针。 • 如果链表中的每个结点既有指向下一个结点的指针,也有指向上一个结点的指针,则称该链表为双向链表,否则称为单向链表。 prev next back 面向对象程序设计
6.9 简单链表及其应用 * • 6.9.2 链表构建与操作 • 1. 定义结点类型 • 链表的结点中可以包括若干个各种类型的数据,结点通常为结构体类型。 • 在创建和操作链表时,通常使用结点指针。因此为了使用方便,我们可以利用类型定义的方法来定义结点指针类型。 • 【例6.39】 prev next back 面向对象程序设计
6.9 简单链表及其应用 * • 6.9.2 链表构建与操作 • 2. 创建无序链表 • 一个链表是有若干个结点连接而成,创建链表实际上是创建链表中的各个结点,并将它们连接起来。 • 函数createLinked( )实现创建链表,其算法为:如果链表为空(head=0),则将该结点设置为表头;如果链表非空,则将该结点加入到链表的末尾。 prev next back 面向对象程序设计
6.9 简单链表及其应用 * • 6.9.2 链表构建与操作 • 3. 访问链表中的结点 • 由于链表中的结点是通过链域连接的,要访问某个结点,必须知道它的上一个结点(头结点例外)。因此,只要知道一个链表的头结点,就可以访问整个链表中的所有结点。 • 通过循环语句,可以获得指定位置的结点的指针。特别地,可以获得尾结点的指针。 • 函数 accessNode(const ptrN, int)。 prev next back 面向对象程序设计
6.9 简单链表及其应用 * • 6.9.2 链表构建与操作 • 4. 插入结点 • 插入结点到指定位置的操作有如下几种情形: • (1) 链表为空(head=0)。 • (2) 链表非空,将结点插入到表头位置(n=1)。 • (3)将结点插入到链表的中间位置。 • (4)将结点插入到链表的末尾。 • (5) 插入点超过链表范围。 • 函数 insertNode(ptrN, ptrN, int)。 prev next back 面向对象程序设计
6.9 简单链表及其应用 * • 6.9.2 链表构建与操作 • 5. 删除结点 • 删除指定位置的结点时也要考虑如下几种情况: • (1) 链表为空(head=0)。 • (2) 链表非空,删除表头(n=1)。 • (3)删除链表中间的结点。 • (4)删除尾结点。 • (5) n超过链表中的结点数。 • 函数 deleteNode(ptrN, int)。 prev next back 面向对象程序设计
6.9 简单链表及其应用 * • 6.9.2 链表构建与操作 • 6. 创建有序链表 • 所谓有序链表,是指链表中的结点按结点的某个成员的大小进行排列。 • 将一个结点插入到有序链表中时,为了保持有序性,要判断插入的位置。 • 函数 insert_sort_node(ptrN , ptrN ) 。 • 通过上述插入函数,可以创建一个有序链表。 • 函数 create_sort_linked() 。 prev next back 面向对象程序设计
6.9 简单链表及其应用 * • 6.9.2 链表构建与操作 • 7. 其它操作 • 输出链表中的所有结点:函数 outputNodes(const ptrN)。(借助于函数accessNode( const ptrN, int) ) • 直接输出链表中的结点:函数 outputNodes1(const ptrN) 。 • 撤消结点所占用的存储空间:函数 deleteLink(ptrN) 。 prev next back 面向对象程序设计