第五课 数组与指针
指明了类型,就指明了操作
特征:
- 相同类型
- 连续存储
可以按下标访问,也可以按地址访问。C++是基于实现的
C++中的二维数组是复合类型,没有Array。
数据类型决定范围和取值方式,什么样的类型定义了什么样的访问方式int len = sizeof(arr)/sizeof(arr[0])
1 | int a[6]; |
C++是允许数组下标越界的,因为越界是有用的前提是空间是合理的
1 | void f (char[] a ){ |
**
所以输出s2时,会一直输出下去**,直到刚好碰到'\0'
没有初始化的空间全部默认为 0xcc,代表中文的烫
利用malloc时不初始化,空间会默认为0xcd,代表中文的屯。【debug版本中打开/GZ开关,方便找到潜在的错误 = 》现在使用/RTC1】
C++中的变量是不会自己初始化的
mallopt指定自己配置的空间是什么【写在代码中的】
valgrind设置栈、堆里面的填充【不修改代码】
指针
指针必须初始化,防止调用垃圾地址并修改了其中的内容

void*
void *v 则 *v是不被运行的。所以**v**可以作为任何类型指针的公共接口,只具有记录地址的作用,是可以被信任的。任何指针都可以赋值给**void ***,但void * 不能赋值给其他指针
清零
int a[100] 全部赋值为0
for循环memset函数(起始地址,大小)则起始地址必须为**void ***1
2
3
4
5
6void memset(void *p,int n){
char *q = (char *)p; // 进行强制类型转换为char *,一个一个字节的删除即可
for(int i=0;i<n;i++){
*(q+i) = 0;
}
}
数组与指针

a 是一个常量指针,数组名是常量指针
- 通过数组下标访问
- 通过指针访问
- 通过数组名访问
动态数组int *p =(int*) malloc (……)
多维数组
通过一维数组不断复合,依然是一段连续的数据。
参数传递:缺少第一维,因为对应的就是指针,指向后面的维度
1 | typedef int T[2]; // |
升维操作:动态多维数组需要借助一维数组来实现,利用升维操作
降维操作p[i]

降维操作q[i][j]

为了能通过q[i][j]的形式表示,则需要q指针指向的是一个小方块,而不是一个具体从存储单元。在这个小方块中,包含若干个的最小存储单元,从而通过j这一坐标找到最小的存储单元**p+11**其实是越界了,方便用数组的形式访问多维数组
小结

数组升维降维
降维

升维

ragged array
java 中的二维数组不是规整的,可能是锯齿状的,不对等的
动态变量
1 | int *p = mall |
在使用new时,会逐个调用constructor,从而实现强制类型转换。OO使得数据进入时能进行部分操作
new malloc 和inline一样,可能会申请不成功,所以需要有效性判定
异常处理
- 可以预见:new可能会失败
- 无法避免
可以由系统处理,也可以自定义处理。为了allocate成功,可以自己选择释放一些特定内存,要么停掉,要么交给系统处理,要么自主修改环境
归还
防止内存泄漏
- 操作符
new、delete - 函数
malloc、freeint *q = new int[8]1
2
3
4int *p1 =new int (8);
int *p2 = malloc(sizeof(int));
int *q = new int[8];
int *q2 = malloc(sizeof(int)*8);
delete q 只调用一个析构函数
delete [] q 逐个调用析构函数
free(q)
如何知道有8个?
- 符号表:耗时+会导致表的大小未定,空间不确定
- 用空间换取时间:在分配内存时,额外用一个空间
**cookie**,cookie中存储块的大小
申请的指针不要随意改变,否则容易归还失败。因此使用时要用int *p1 = p;
RAII
compiler会自动调用destructor,确保对象被释放。生命周期结束的时候会自动调用delete,利用析构函数的自动调用防止内存泄漏,确保资源的初始化。
unique_ptr shared _ptr 解决资源共享或者独享问题
1 | class A{ |
A a;
A b =a;
会导致悬挂指针idle point,a 和 b 的生命周期结束不一致。
其他
Sturct
定义数据的顺序会影响到内存的占用,会数据对齐
Union

B的存储空间是最大占有的内存,所有的域代表一个公共的空间,里面的内容共享一块存储空间。
对于struct,
matrix
表示方法1:
表示方法2:
两种访问方式:
数组 — 多态性

