【学习笔记】C++语言程序设计(郑莉):数组、指针与字符串

  • 1. 数组
    • 1.1 数组的声明与使用
    • 1.2 数组的存储与初始化
    • 1.3 数组作为函数参数
    • 1.4 对象数组
  • 2. 指针
    • 2.1 内存空间的访问方式
    • 2.2 指针变量的声明
    • 2.3 与地址相关的运算 “*” 和 “&”
    • 2.4 指针的赋值
    • 2.5 指针运算
    • 2.6 用指针处理数组元素
    • 2.7 指针数组
    • 2.8 用指针作为函数参数
    • 2.9 指针型函数
    • 2.10 指向函数的指针
    • 2.11 对象指针
  • 3. 动态分配内存
  • 4. 用vector创建数组对象

1. 数组

数组是具有一定顺序关系的若干对象的集合体,组成数组的对象称为该数组的元素。数组元素用数组名与带方括号的下标表示,同一数组的各元素具有相同的数据类型。

1.1 数组的声明与使用

  • 数组声明

      // 数组类型声明一般形式数据类型 标识符[常量表达式1][常量表达式2]...;
    

    声明一个数组类型,应包含:

    • 确定数组的名称
    • 确定数组元素的类型
    • 确定数组的结构(包括数组维数,每一维的大小等)
  • 数组的使用

      // 数组使用一般形式数组名[下标表达式1][下标表达式2]...;
    
    • 数组元素的下标表达式可以是任意合法的算术表达式,其结果必为整数
    • 数组元素的下标值不得超过声明时所确定的上下界,否则运行时将出现数组越界错误
    // 数组声明与使用
    #include<iostream>
    using namespace std;int main() {int a[10], b[10];               //定义两个有10个元素的一维数组a,bfor (int i = 0; i < 10; i++) {  //使用for循环对两个数组进行赋值a[i] = i * 2 - 1;b[10 - i - 1] = a[i];}for (int i = 0; i < 10; i++) {  //使用for循环输出结果cout << "a[" << i << "]=" << a[i] << "   ";cout << "b[" << i << "]=" << b[i] << endl;}return 0;
    }
    

1.2 数组的存储与初始化

  • 数组的存储
    数组元素在内存中是顺序、连续存储的。数组元素在内存中占据一组连续的存储单元,逻辑上相邻的元素在物理地址上也是相邻的。一维数组是简单的按照下标的顺序,连续存储的。二维数组在内存中是按行存放的,即先放第1行,再放第2行…每行中的元素是按列下标由小到大的次序存放
  • 数组的初始化
    数组的初始化就是在声明数组时给部分或全部元素赋初值。对于基本类型的数组,初始化过程就是给数组元素赋值,对于对象数组,每个元素都是某个类的一个对象,初始化就是调用该对象的默认构造函数
    定义数组时:

    • 如果列出全部元素的初值,可以不用说明元素个数
    • 当指定的初值个数小于数组大小时,剩下的数组元素会被赋予0值
    • 如果没有指定任何一个元素的初值
      • 对于静态生存期的数组,每个元素仍然会被赋予0值
      • 对于动态生存期的数组,每个元素的初值都是不确定的
    • 声明为常量的数组,必须给定初值
    // 数组的初始化
    // 列出全部元素的初值
    int a[3] = {1, 1, 1};
    // 列出全部元素的初值,可以不用说明元素个数
    int a[] = {1, 1, 1};
    // 指定的初值个数小于数组大小时,剩下的数组元素会被赋予0值
    float fa[5] = {1.0, 2.0, 3.0};
    // 声明为常量的数组
    const float fa[5] = {1.0, 2.0, 3.0};
    

1.3 数组作为函数参数

用数组元素作为调用函数的参数,则实参和形参都应该是数组名,且类型要相同。和普通变量作参数不同,使用数组名传递数据时,传递的是地址,也就是说如果在被调函数中对形参数组元素值进行改变,主调函数中实参数组的相应元素值也会改变。

1.4 对象数组

  • 对象数组声明语法格式:

      类名 数组名[常量表达式];
    
  • 访问对象数组元素语法格式:

      数组名[下标表达式].成员名;
    

对象数组的初始化过程,实际上就是调用构造函数对每一个元素对象进行初始化的过程。当一个数组中的元素对象被删除时,系统会调用析构函数来完成扫尾工作。


2. 指针

2.1 内存空间的访问方式

在C++程序中如何利用内存单元存取数据?
一是通过变量名,而是通过地址。具有静态生存期的变量在程序开始运行之前就被分配了内存空间。具有动态生存期的变量,是在程序运行时遇到变量声明语句时被分配内存空间的。

2.2 指针变量的声明

指针也是一种数据类型,具有指针类型的变量称为指针变量。指针变量是用于存放内存单元地址的。通过变量名访问一个变量是直接的,而通过指针访问一个变量是间接的。声明指针的语法格式为:

数据类型 *标识符;

这里 * 表示声明的是一个指针类型的变量

int * ptr;  // 定义了一个指向int型数据的指针变量

2.3 与地址相关的运算 “*” 和 “&”

  • “*” 称为指针运算符,表示获取指针所指向的变量的值
  • “&” 称为取地址运算符,用来得到一个对象的地址
// * 出现在声明语句中,在被声明的变量名之前,表示声明的是指针
int * p;           //声明p是一个int型指针
// * 出现在执行语句中或声明语句的初始化表达式中,表示访问指针所指向对象的内容
cout << *p;        // 输出指针p所指向的内容
// & 出现在变量声明语句中位于被声明的变量左边时,表示声明的是引用
int &rf;           // 声明一个int型的引用rf
// & 在给变量赋初值时出现在等号右边或在执行语句中作为一元运算符出现时,表示取对象的地址
int a, b;
int * pa, *pb = &b;
pa = &a;

2.4 指针的赋值

指针赋值有两种方法:

  • 在定义指针的同时进行初始化赋值。语法形式为:

      存储类型 数据类型 * 指针名 = 初始地址;
    
  • 在定义之后,单独使用赋值语句。语法格式为:

      指针名 = 地址;
    

一个数组,可以用它的名称来直接表示它的起始地址。数组名称实际上就是一个不能被赋值的指针,即指针常量

int a[10];      //定义int型数组
int *ptr = a;   //定义并初始化int型指针

关于指针的类型,还应该注意:

  • 可以声明指向常量的指针,此时不能通过指针来改变所指对象的值,但指针本身可以改变,可以指向另外的对象。

    int a;
    const int *p1 = &a;  //p1是指向常量的指针
    int b;
    p1 = &b;   //正确,p1本身的值可以改变
    *p1 = 1;   //错误,不能通过p1改变所指的对象
    
  • 可以声明指针类型的常量,这是指针本身的值不能被改变。
    int * const p2 = &a;  //声明p2是指针常量
    p2 = &b;              //错误,p2是指针常量,值不能改变
    
  • 一般情况下,指针的值只能赋给相同类型的指针。但是任何类型的指针都可以赋值给void类型指针。(void指针一般只在指针所指向的数据类型不确定时使用)。

2.5 指针运算

  • 指针是一种数据类型。与其他数据类型一样,指针变量也可以参与部分运算,包括算术运算、关系运算和逻辑运算。指针可以和整数进行加减运算,比如有指针p1和整数n1,则p1+n1表示指针p1当前所指位置后方第n1个数的地址,p1-n1表示指针p1当前所指位置前方第n1个数的地址。“指针++”或“指针- -”表示指针当前所指下一个或前一个数据的地址
  • *(p1+n1)表示p1当前所指后方第n1个数的内容,也可以写作p1[n1]
  • 一般来讲,指针的算术运算是和数组的使用相联系的,因为只有在使用数组时,才会得到连续分布的可操作内存空间
  • 0专用于表示空指针,也就是一个不指向任何有效地址的指针

2.6 用指针处理数组元素

int array[5];

声明了一个存放5个int类型数的一维数组,数组名array就是数组的首地址(第一个元素的地址),即array和&array[0]相同。数组中5个整数顺序存放,因此,通过数组名这个地址常量和简单的算术运算就可以访问数组元素。数组中下标为 i 的元素就是*(数组名+ i ),例如,*array就是array[0],*(array+3)就是array[3]

2.7 指针数组

如果一个数组的每个元素都是指针变量,这个数组就是指针数组。声明一维指针数组的语法形式为:

数据类型 * 数组名[下标表达式];
int *pa[3];

声明了一个int类型的指针数组pa,其中有3个元素,每个元素都是一个指向int型数据的指针。

2.8 用指针作为函数参数

子函数运行过程中,通过形参指针对数据值的改变也同样影响着实参指针所指向的数据值。C语言中,以指针作为函数的形参有三个作用:

  • 使实参与形参指针指向共同的内存空间,以达到参数双向传递的目的。C++中通过引用实现该功能。
  • 减少函数调用时数据传递的开销。C++中有时通过引用实现,有时使用指针
  • 指向函数的指针传递函数代码的首地址

2.9 指针型函数

当一个函数的返回值是指针类型时,这个函数就是指针型函数。使用指针型函数的最主要的目的就是要在函数结束时把大量的数据从被调函数返回到主调函数中。指针型函数的一般定义形式为:

数据类型 * 函数名(参数表){函数体
}

数据类型表明函数返回指针的类型;函数名和 “*” 标识了一个指针型的函数;参数表中是函数的形参列表。

2.10 指向函数的指针

函数指针就是专门用来存放函数代码首地址的变量。声明函数指针的一般语法为:

数据类型 (*函数指针名)(形参表)

数据类型说明函数指针所指函数的返回值类型;*函数指针名指明一个函数指针的名称;形参表列出来该指针所指函数的形参类型和个数。
由于对函数指针的定义在形式上比较复杂,所以一般使用typedef,例如:

typedef int(*Functions)(double);

声明了Functions “有一个double形参,返回类型为int的函数指针”类型的别名。所以需要声明这一类型的变量时,可以直接使用:

Functions funcPtr;

声明了一个具有该类型的名称为funcPtr的函数指针。
函数指针在使用之前要进行赋值,是指针指向一个已经存在的函数代码的起始地址,一般语法为:

函数指针名 = 函数名;

通过指针访问类的静态数据成员示例:

#include<iostream>
using namespace std;//Point类定义
class Point {public:Point(int x = 0, int y = 0) :x(x), y(y) {  //Point类构造函数count++;}Point(const Point &p) :x(p.x), y(p.y) {      //Point类复制构造函数count++;}~Point() {                                 //析构函数count--;}int getX() const{                            //获取x的成员函数return x;}int getY() const {                          //获取y的成员函数return y;}static int count;                           //静态成员private:int x, y;
};int Point::count = 0;int main() {//通过指针访问类的静态数据成员int* ptr = &Point::count;                                  //定义指向Point类静态成员count的指针ptrPoint a(4, 5);                                               //定义Point对象acout << "Point A: " << a.getX() << "," << a.getY() << " ";  //获取A点的坐标cout << "Object count=" << *ptr << endl;                  //计算对象个数Point b(a);                                                 //定义Point对象bcout << "Point B: " << b.getX() << "," << b.getY() << " ";  //获取B点的坐标cout << "Object count=" << *ptr << endl;                  //计算对象个数return 0;
}

运行结果为:

2.11 对象指针

对象指针就是用于存放对象地址的变量。声明对象指针的一般语法为:

类名 *对象指针名;

使用对象指针访问对象成员的语法形式为:

对象指针名->成员名;(*对象指针名).成员名

3. 动态分配内存

建立和删除堆对象使用两个运算符:new 和 delete

  • 运算符 new 的功能是动态分配内存,或者称为动态创建堆对象。如果内存申请成功,new 运算符便返回一个指向新分配内存首地址的类型的指针,可以通过这个指针对堆对象进行访问;如果申请失败,会抛出异常。语法格式为:

      new 数据类型(初始化参数列表);
    
  • 运算符 delete 用来删除由 new 建立的对象,释放指针所指向的内存空间。语法格式为:

      delete 指针名;
    
  • 运算符 new 也可以创建数组类型的对象。用 new 建立的数组,用 delete 删除时在指针名前面要加“[]",即“delete[] 指针名 ;” 创建数组类型对象语法格式为:

      new 类型名[数组长度];
    

4. 用vector创建数组对象

数组是继承于C语言的一种表示群体数据的方法,具有简单、高效的优点,但无论是静态数组,还是用new动态创建的数组,都难以检测下标越界的错误。为此,C++提供了被封装的动态数组–vector。用vector定义动态数组的形式为:

vector<元素类型>数组对象名(数组长度);
int x = 10;
vector<int>arr(x);  //定义了一个大小为10的int型动态数组对象arr

与普通数组不同的是,用vector定义的数组对象的所有元素都会被初始化。如果数组的元素类型为基本数据类型,则所有元素都会被以0初始化,如果数组元素为类类型,则会调用类的默认构造函数初始化。另外,初值也可以自己指定,但只能为所有元素指定相同初值,形式为:

vector<元素类型>数组对象名(数组长度,元素初值);

对vector数组对象元素的访问形式,与普通数组一致:

数组对象名[下标表达式]

但是vector数组对象的名字表示的就是一个数组对象,而非数组的首地址,因为数组对象不是数组,而是封装了数组的对象。vector定义的数组对象具有一个重要的函数成员 size(),它会返回数组的大小


课程链接:https://www.bilibili.com/video/BV1iF411Y74v

【学习笔记】C++语言程序设计(郑莉):数组、指针与字符串相关推荐

  1. 郑莉版java第三章答案_java语言程序设计(郑莉)第七章课后习题答案.docx

    java语言程序设计(郑莉)第七章课后习题答案.docx 还剩 10页未读, 继续阅读 下载文档到电脑,马上远离加班熬夜! 亲,喜欢就下载吧,价低环保! 内容要点: if (matrix.isTria ...

  2. java语言程序设计郑莉课后答案_Java语言程序设计郑莉课后习题答案.pdf

    (1) 构造方法的方法名与类名相同: Java 语言程序设计(郑莉) (2 ) 构造方法没有返回类型(修饰符void 也不能有): 第二章习题答案 (3 ) 构造方法通常被声明为公有的(public) ...

  3. 郑莉java课后答案,Java语言程序设计(郑莉)第三章课后习题答案

    <Java语言程序设计(郑莉)第三章课后习题答案>由会员分享,可在线阅读,更多相关<Java语言程序设计(郑莉)第三章课后习题答案(10页珍藏版)>请在人人文库网上搜索. 1. ...

  4. java语言程序设计郑莉课后答案_java语言程序设计郑莉第九篇课后习题答案.docx...

    java语言程序设计郑莉第九篇课后习题答案.docx 还剩 36页未读, 继续阅读 下载文档到电脑,马上远离加班熬夜! 亲,很抱歉,此页已超出免费预览范围啦! 如果喜欢就下载吧,价低环保! 内容要点: ...

  5. c 语言程序设计第四版郑莉答案,C 语言程序设计郑莉(第4版)

    <C++语言程序设计(在线教学版?第4版)/清华大学计算机系列教材,普通高等教育"十一五"规划教材>针对程序设计的初学者,以面向对象的程序设计思想为主线,以通俗易懂的方 ...

  6. java语言程序设计郑莉课后答案_java语言程序设计 第2版 (郑莉)课后习题答案.doc...

    java语言程序设计 第2版 (郑莉)课后习题答案.doc JAVA语言程序设计第2版郑莉第二章习题答案1什么是对象.类,它们之间的联系答1)对象是包含现实世界物体特征的抽象实体,它反映系统为之保存信 ...

  7. (转载)[python学习笔记]Python语言程序设计(北理工 嵩天)

    作者:九命猫幺 博客出处:http://www.cnblogs.com/yongestcat/ 欢迎转载,转载请标明出处. 如果你觉得本文还不错,对你的学习带来了些许帮助,请帮忙点击右下角的推荐 阅读 ...

  8. 郑莉c 语言程序设计答案,C语言程序设计(郑莉)课后习题答案

    delete CatHouse[i]; TelepathicFunction(); } return 0; } void TelepathicFunction() { cout << \a ...

  9. c 语言 清华大学郑莉,c 语言程序设计郑莉清华大学答案

    每一个子直到需要都已的开经明具量任务确所发工,语言程估算需要进行列的一系处理,语言程开发把待的软件细分,)估总工作量开发为(得到的方软件法称算法,们加把它然后起来,杂性项目的复由于. 序设学答额由贸易 ...

  10. 编译原理学习笔记2——高级程序设计语言概述

    编译原理学习笔记2--高级程序设计语言概述 2.1常用的高级程序设计语言 2.2程序设计语言的定义 2.2.1语法 2.2.1语法 2.2.3程序语言的基本功能和层次机构 2.2.4程序语言成分的逻辑 ...

最新文章

  1. 总监调岗至前台,企业被判赔偿26万,法院:“侮辱性调岗”违法!
  2. Qlik与百度开放云建立战略联盟,让中国企业通过强大的可视化分析看到数据背后的整个故事...
  3. 《响应式Web设计全流程解析》一1.2 静态设计稿舒适区
  4. 【原创】MyEclipse反编译添加jadclipse_3.3.0 曲折的完美解决
  5. TCP/IP协议(3):数据链路层
  6. VS2010Web默认的浏览器设置和VS里调试JavaScript代码的设置
  7. HashMap,HashTable,ConcurrentHashMap面试总结!!!
  8. JavaWeb--数据库添加
  9. C# WinForm ProgressBar垂直显示进度和从右向左显示进度
  10. 数模学习笔记——微分方程
  11. best wavelet guide
  12. 查看swintransformer的网络结构.children()
  13. 任正非:鸿蒙最快1年可媲美iOS;首例Apple Card用户遭盗刷;Firefox 69.0.3 发布 | 极客头条...
  14. Mbs Framework 简介
  15. 合并Python列表的魔幻12法
  16. java实时监控系统_JavaMonitor
  17. 注册邮箱账号十大品牌分析
  18. USB鼠标设备驱动程序简单实现(一)
  19. mysql双一参数_mysql的双1设置
  20. c语言 字符串 正序再倒序_MySQL - 字符串索引优化

热门文章

  1. 计算机专业考研统考的211院校,第一批20考研热门院校报录比汇总,包含大量985&211...
  2. android异步任务载入数据界面实现
  3. 广义二项式定理求解系数
  4. 股票交易android开发(十二)
  5. GRPS 与WIFI环境下,REST中的Delete方法不被支持
  6. 关于汉EV碰撞试验,不要看比亚迪说了什么,要看没说什么
  7. 要从哪些方面提升H5游戏的营销效果
  8. 19.13-PLC和PLC的ModbusRTU通信及Modbus_Slave指令讲解
  9. 反激电路元器件参数的运算公式
  10. 大部分工业机器人都采用二级计算机控制,焊接机器人示教器解读.ppt