IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> 清华大学C++课程学习笔记——第六章 数组指针字符串 -> 正文阅读

[C++知识库]清华大学C++课程学习笔记——第六章 数组指针字符串

(一)数组

1.概念:

  • 具有一定顺序关系的若干相同变量的集合体(数组的顺序信息,与循环语句配合,依次处理批量数据)
  • 数组元素的地址是连续的,与逻辑上的次序相邻
  • 数组名字是数组元素的内存地址,数组名是一个常量,不能被赋值

2.定义&使用:类型说明符 数组名[常量表达式][常量表达式]

  • 先定义后使用,逐个引用数组元素
  • 一维数组的初始化:列出全部元素的初始值;只给一部分元素指定初始值 ;列出全部数组元素初值,不指定数组长度
  • 二维数组的初始化:列出所有的初值,按顺序进行初始化;只对部分元素进行初始化;列出全部初始值,一维下标的个数可以省略;
    【小bug,cout.width()需要直接在main函数里使用,不然会报错error: 'cout' does not name a type
    eg:
    循环从键盘读入若干选择题答案,计算并输出每个答案的正确率,直到输入ctrl+z为止
    每组连续输入5个答案,每个答案可以是a,b,c,d
# include<iostream>
using namespace std;

int main(){
	const char key[] = {'a','b','c','d','a'};
	const int Num_question = 5;
	char c;
	int question = 0, Num_correct =0;
	cout<<"Enter the"<<Num_question<<"question tests:"<<endl;
	while(cin.get(c)){
		if (c!='\n')
		{
			if (c == key[question])
			{
				Num_correct++;
				cout<<"-";
			}
			else
			{
				cout<<"*";
			}
			question++;	
		}
		else
		{
			cout<<"Score"<<static_cast<float>(Num_correct)/Num_question*100<<"%";
		}	
	}
	return 0;
}

3.数组作为函数的参数:

  • 数组作实参,与单个变量一样;;
  • 数组名作参数,形、实参数都应是数组名,类型要一致,传送的是数组的首地址;
  • 对形参数组的改变会影响到实参数组(希望改变和不希望改变)

4.对象数组

a.定义:类名 数组名[元素个数]
b.访问:通过下标访问:数组名[下标].成员名
c.构造和析构:

  • 构造数组时,元素所属的类未声明构造函数,则采用默认构造函数
  • 各元素对象的初值要求为相同的值,可以声明具有默认形参值的构造函数
  • 各元素对象的初值要求为不同的值,需要声明带形参的构造函数
  • 数组中每一个对象被删除时,系统都有调用一次析构函数

5.基于范围的for循环

a.背景:自动遍历整个容器
b.使用:

for (dataType rangeVariable : array)
    statement;

6.Vector对象

a.背景:使用动态数组时的操作过于繁琐,希望能够自动创建和删除对数组进行下标越界检查
b.定义:vector<元素类型>数组对象名(数组长度)
vector5
c.使用

  • 对数组元素的引用:vector 对象名[下标表达式]
  • 获得数组长度,用size函数 vector 对象名.size()
  • 需要定义头文件

(二)指针

1.内存空间的访问

  • 通过变量名访问
  • 通过地址访问

2.指针的概念

  • 内存地址,用于间接访问内存单元
  • 指针变量:用于存放地址的变量

3.定义与使用

a.初始化:存储类型 数据类型 *指针名 = 初始地址 int*pa = &a

  • 不仅要说明该变量是指针,还要说明他指向的对象是什么类型(取数据的多少字节)
  • 可以用一个合法的指针去初始化另一个指针变量
  • 不能用一个内部非静态变量去初始化static指针
    b.赋值:指针名 = 地址
  • “地址”中存放的数据类型与指针类型必须相符
  • 向指针变量赋的值必须使地址常量或变量,不能是普通整数(0例外,可以赋给指针,表示空指针nullptr更安全的空指针)
  • 允许定义void类型的指针,只能用来存放地址,而不能用来访问地址。
  • "*“指针运算符;”&"地址运算符

4.常量

【牛客网经常有的概念辨析】
a.指向常量的指针
【牛客网经常有的概念辨析】

  • 不能通过指向常量的指针改变所指对象的值,但是指针本身可以改变指向另外的对象
int a;
const int*p1 = &a;//p1是指向常量的指针
int b;
p1 = &b;//p1本身的值可以改变
*p1 = 1 ;//编译时出错,不能通过p1改变所指的对象

b.指针类型的常量
若声明为指针常量,则指针本身的值不能被改变

int a;
int *const p2 = &a;
p2 = &b;//p2是指针常量,值不能改变

5.指针运算

【牛客网中有考察二维数组的地址运算,然后求最后输出的结果】
a.算术运算:
(总是指向数据的完整起始位置,指针指向连续存储的同类型数据时,指针与整数的加减法和自增自减运算才有意义)

  • 与整数的加减运算
  • 指针++、–运算
    b.关系运算:
  • 指向相同数据类型数据指针之间可以进行关系运算
  • 指针可以和0进行关系运算

6.指针与数组的关系

a. 指向数组元素的指针
【牛客网上是题目通常会有好几层*从数组的第一层往外分析】
*pa 就是a[0], (pa+1)就是a[1],…,(pa+i)就是a[i]
b.指针类型:数组的元素是指针类型
eg. 二维数组就相当于由一维数组构成的数组

7.指针作为参数

a.优点:

  • 需要数据双向传递
  • 需要传递一组数据,只传首地址运行效率比较高
    eg:传递一个数的整数部分和小数部分
    【浮点数在计算机里是近似存储的,两个数相减满足某个精度就能视为相等】

8.指针类型的函数

函数的返回值是指针,该函数就是指针类型的函数
a.定义形式

存储类型 数据类型 *函数名()
{}

b.注意

  • 不要将非静态的局部地址用作函数的返回值(非静态的地址,离开后地址就失效了)
  • 返回的指针在主调函数中依然合法有效的地址
  • 子函数中通过动态内存分配new操作取得的内存地址返回给主函数是合法有效的

9.指向函数的指针

a.容纳的是指向函数代码的起始地址

存储类型 数据类型(*函数指针名)();

函数类型的指针
存储类型 数据类型 *函数指针名();
b.典型用途——实现函数回调

  • 通过函数指针调用函数,可以在相似时间灵活使用不同的方法
  • 调用者不关心谁是被调用者,需要知道存在一个具有特定原型和限制条件的被调用函数
    eg 函数指针,编写一个compute,对两个整数进行各种计算,有一个形参为指向具体算法函数的指针,根据不同的实参函数,用不同的算法(最大值、最小值、和)进行计算。
# include<iostream>
using namespace std;

int compute (int a,int b,int(*func)(int,int))
{return func(a,b);}

int max(int a,int b)
{return((a>b)?a:b);}

int min(int a,int b)
{return((a>b)?b:a);}

int sum(int a, int b)
{return a+b;}

int main(){
	int a,b,res;
	cout<<"请输入整数a"<<endl;
	cin>>a;
	cout<<"请输入整数b"<<endl;
	cin>>b;
	res = compute(a,b,&max);
	cout<<"Max of"<<a<<"and"<<b<<"is"<<res<<endl;
	res = compute(a,b,&min);
	cout<<"Min of"<<a<<"and"<<b<<"is"<<res<<endl;
	res = compute(a,b,&sum);
	cout<<"Sum of"<<a<<"and"<<b<<"is"<<res<<endl;	
}

10.对象指针

a.定义形式:类名 *对象指针名
b.通过指针访问对象成员:对象指针名—>成员名
ptr->get()相当于(*ptr).getx()
c.this指针:指向当前对象自己的指针

  • 隐含于类的每一个非静态成员函数中
  • 指出成员函数所操作的对象
    当通过一个对象调用成员函数时,系统先将该对象的地址赋给this指针,然后调用成员函数,成员函数对对象的数据成员进行操作,就隐含使用了this指针
    11.智能指针
    背景:垃圾回收技术
智能指针类型特点
unique_ptr不允许多个指针共享资源,可以用标准库中的move函数转移指针
shared_ptr多个指针共享资源
weak_ptr可复制shared_ptr,但其构造或者释放对资源不产生影响

(三)字符串

1.C风格字符串

a.具体说明:各个字符连续、顺序存放,每个字符占一个字节,以’\0’结尾,相当于一个隐含创建的字符串常量数组。
b.缺点:

  • 执行连接、拷贝、比较等操作,都需要显式调用库函数
  • 字符串长度不确定时,需要new和delete比较繁琐
  • 容易发生下标越界的问题

2.string类

a.有常用的操作函数

(比较浮点数的大小端)

(四)动态分配与释放内存

1.动态申请操作符 new

new 类型名T(初始化参数列表)
功能:在程序执行期间,申请用于存放T类型对象的内存空间,并依据初始列表赋以初值

2.释放内存操作符 delete

功能:释放指针p所指的内存,p必须是new操作的返回值

3.申请和释放动态数组

分配:new 类型名T [数组长度] 数组长度可以是任何整数类型的表达式,在运行时计算

  • 一个二维数组的首地址就是指向一维数组的指针
    释放:delete[ ] 数组名 p
  • 释放指针p所指向的数组(不写[]就会只释放元素对应的这一个)
  • p必须用new 分配得到的数组首地址

4.将动态数组封装成类

优点:可以在访问数组元素前检查下标是否越界

(五)复制构造

1.浅层复制

实现对相减数据元素的一一对应复制

2.深层复制

当被复制的对象数据成员是指针类型时,不是复制该指针成员本身,而是将指针所指对象进行复制

3.移动构造

有些复制构造是不必要的,只需要移动对象即可,将源对象资源的控制权全部交给目标对象(省去了构造和删除临时对象的过程)

  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2022-01-11 23:48:36  更:2022-01-11 23:49:52 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 11:01:49-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码