1、数组
(1)数组是由若干同一类型的数据元素构成的有序集合。
(2)计算机在编译程序时确定数组长度,而变量在运行时才会有值,因此,定义数组的时候必须使用常量表达式指定数组在各维度上的下标,而不能使用变量。
(3)数组的初始化顺序为从左到右,不能跳过某个元素而初始化后面的元素。
(4)带初始化的二维数组定义可以省略行长,但不能省略列长。Eg: int array[][4] = {{1,2},{2,3,4,5},{4,5,6}};
(5)所有使用多维数组解决的问题都可以改为用一维数组来解决。
2、指针
(1)指针是存放内存地址的一种数据类型。
(2)指针可以是常量,例如数组名就是一个指针常量,表示该数组在内存中的首地址。指针也可以是变量。可以使用指针常量和指针变量直接操作它们所指向的内存空间中的数据。
(3)在程序中既可以修改指针变量所指向内存中的数据,也可以修改指针变量所指向的内存地址。
(4)指向行的指针变量:
定义形式:数据类型(*指针变量名)【行长度】
可以用来操作二维数组。指向行的指针变量的数据类型必须与该指针变量要指向的二维数组的数据类型一致,行长度必须与二维数组的列数相同。
int array[][3] = {{1,2,3},{4,5,6}};
int (*p)[3] = &array[0]; //int (*p)[3] = array; 等价的
cout << p[0][0] << endl;
上面是使用指向行的指针变量操作二维数组,也可以使用下面普通的指针变量操作二维数组。
int array[][3] = {{1,2,3},{4,5,6}};
int * p = &array[0][0]; //int * p = array[0]; 等价的
cout << p[0] << " " << p[1] << " " << p[2] << " " << p[3] << endl;
(5)指针数组:
定义形式:数据类型 * 数组名【长度】
int array[][3] = {{1,2,3},{4,5,6}};
int * p[2];
for(int i=0;i<2;i++){
p[i] = array[i];
}
cout << p[0][0] << endl;
(6)常量指针:
定义形式:const 数据类型 * 变量名
一个指向常量的指针变量,即所存储的内存地址可以改变,但通过常量指针只能从所指向的内存读取数据,但不能修改内存中的数据。
(7)指针常量:
定义形式:数据类型 * const 变量名
是一个常量而非变量,因此其内容是固定不变的,但是可以通过指针常量修改它所指向的内存中的数据。定义指针常量时必须初始化。可以将一个指针同时定义为常量指针和指针常量,此时,既不能改变指针所指向的内存地址,也不能通过该指针修改内存中的数据。
(8)堆是内存中的一片空间,它允许程序运行时申请某一长度的内存空间。堆内存分配就是动态内存分配。在C++中使用new和delete这两个运算符完成堆内存分配和释放的操作。使用new分配的内存必须使用delete来释放,否则会造成内存泄露。当系统出现大量内存泄露时,系统可用资源也会相应减少、导致计算机处理速度变慢,当系统资源枯竭时甚至会造成系统崩溃。使用new分配堆内存时要区分【】和(),【】中的表达式指定了元素数目,而()中的表达式指定了内存的初值。
int a = 3;
int * p1 = new int[a]; //分配了三个int型元素大小的内存空间
int * p2 = new int(a); //分配了一个int型元素大小的内存空间,且其初始值为3,等价于:int * p2 = new int , p2 = a;
例一:使用堆内存分配方式实现学生成绩录入功能。
#include <iostream>
using namespace std;
int main(){
int * p;
int n;
cout << "请输入学生的人数。" << endl;
cin >> n;
p = new int[n];
if(p == NULL){
cout << "堆内存分配失败!" << endl;
return 0;
}
for(int i=0;i<n;i++){
cout << "请输入第" << i+1 << "个学生的成绩。" << endl;
cin >> *(p + i);
}
for(int k=0;k<n;k++){
cout << "第" << k+1 << "个学生的成绩是:" << p[k] << endl;
}
delete []p;
return 0;
}
注意:
<1>使用new运算符申请堆内存,会返回申请到的内存空间的首地址。在程序中将这个首地址保存在指针变量中。然后就可以使用该指针变量操作分配的堆内存空间。
<2>当申请分配的内存太大、系统资源不够时,堆内存分配会失败,此时会返回NULL。因此,分配内存后,应判断返回值是否是NULL,如果是NULL则报错并退出程序。
(9)由于const引用不需要修改所引用对象的值,所以const引用可以使用常量对其进行初始化,而非const引用则不可以。
Eg:const int &a = 3;