目录
一、数组
数组:是由一批相同类型的元素(element)的集合所组成的数据结构,分配一块连续的内存来存储。
下标索引:从0开始。
#include "iostream"
using namespace std;
int main(){
int array[5]; // 得到了一个可以存放5个元素的整型数组
array[0] = 11; // 往数组里存值
array[1] = 22;
array[2] = 33;
array[3] = 44;
array[4] = 55;
cout << array[0] << endl; // 从数组里取值
cout << array[1] << endl;
cout << array[2] << endl;
cout << array[3] << endl;
cout << array[4] << endl;
return 0;
}
1.1 数组声明与赋值
int array[] = {11, 22, 33, 44, 55};
1.2 数组的特点
特点1:任意类型均可创建数组
- 基本数据类型:int、float、double、char、string、bool等
- 复合数据类型:结构体、联合体等
- 指针类型:int*、char*、float*等
- 枚举类型:enum
均可形成数组。
特点2:固定大小
C++数组,一旦定义完成,其大小(长度)即固定。
int array[5];
int array[] = {11, 22, 33, 44, 55};
如上代码,无论哪种方式定义,数组v的大小固定为5。
特点3:内存连续且有序
如下数组定义:
int v[] = {1, 2, 3, 4, 5};
数组内存空间是连续分配的,并且每个元素分配大小取决于存放类型
- char 1字节
- int 4字节
- double 8字节等
- 无论何时访问数组元素,均一致(手动修改值除外),如v[0],取出的都是数值1
- 也是基于此确保数组元素类型一致,比如int数组每个元素4字节的空间,无法存储double数值
- 通过 sizeof(数组)/sizeof(数组某元素) 可以得到数组元素个数
特点4:C++无数组下标越界错误
#include "iostream"
using namespace std;
int main(){
int array[] = {11, 22, 33, 44, 55};
cout << array[100] << endl; // 从数组里取值
return 0;
}
特点5:数组变量不记录数据
如下数组定义:
int v[] = {1, 2, 3, 4, 5};
数组变量v本身:
- 并非记录了数组内全部元素(即:不存数据)
- 而是记录了v[0]元素的内存地址
数组元素访问规律如下:
- 通过数组变量(如v)记录下标0元素内存位置,即可找到v[0]
- 通过v[0]地址 + 单个元素空间大小(如int数组,4字节),即可找到v[1]
- 通过v[1]地址 + 4字节,即可找到v[2]
- ……
- 以此类推
1.3 遍历数组
普通for循环
#include "iostream"
using namespace std;
int main(){
int array[] = {11, 22, 33, 44, 55};
for (int i = 0; i < sizeof (array)/sizeof (array[0]); ++i) {
cout << array[i] << endl;
}
return 0;
}
foreach增强循环
#include "iostream"
using namespace std;
int main(){
int array[] = {11, 22, 33, 44, 55};
for (int element : array) {
cout << element << endl;
}
return 0;
}
1.4 字符数组
"hello"; // 方式一
char s[] = "hello"; // 方式二
char * s = "hello"; // 方式三
上述代码,方式一(字面常量)和 方式二定义的字符串,其本质都是:字符数组。
即:
"hello";
char s[] = "hello";
均可以表现为:
char s[] = {'h', 'e', 'l', 'l', 'o', '\0'};
注意:在字符数组中,额外在最后添加一个元素\0(空字符),作为结束标记。
#include "iostream"
using namespace std;
int main(){
char s[] = "hello";
for (char c : s) {
cout << c << endl;
}
return 0;
}
1.5 多维数组
二维数组
#include "iostream"
using namespace std;
int main(){
int v1[2][2]; // 声明二维数组
v1[0][0] = 1;
v1[0][1] = 2;
v1[1][0] = 3;
v1[1][1] = 4;
cout << v1[0][0] << endl;
int v2[2][2] = {{1,2},{3,4}}; // 二维数组
cout << v2[1][0] << endl;
return 0;
}
三维数组
#include "iostream"
using namespace std;
int main(){
// 三维数组
int v3[2][2][2] = {{{1,2},{3,4}},{{5,6},{7,8}}};
cout << v3[0][0][0] << endl; // 1
return 0;
}
遍历
二维数组
#include "iostream"
using namespace std;
int main(){
int v[2][3] = {{1, 2, 3}, {4, 5, 6}};
// 遍历二维数组v,使用sizeof
for(int i = 0; i < sizeof(v)/sizeof(v[0]); i++){
for(int j = 0; j < sizeof(v[i])/sizeof(v[i][0]); j++){
cout << v[i][j] << " ";
}
cout << endl;
}
return 0;
}
三维数组
#include "iostream"
using namespace std;
int main(){
int array[2][2][2] = {{{1,2},{3,4}},{{5,6},{7,8}}};
for (int i = 0; i < sizeof(array)/sizeof(array[0]); i++) {
for (int j = 0; j < sizeof(array[i])/sizeof(array[i][0]); j++) {
for (int z = 0; z < sizeof(array[i][j])/sizeof(array[i][j][0]); z++) {
cout << array[i][j][z] << " ";
}
cout << endl;
}
cout << endl;
}
return 0;
}
1.6 指针
指针基础
指针:特定类型数据在内存中的存储地址,即内存地址。
#include "iostream"
using namespace std;
int main(){
int num = 10;
int *p = #
cout << p << endl; // 0xd151fffcd4
cout << *p << endl; // 10
return 0;
}
野指针与空指针
野指针:被声明但未初始化(赋值)的指针。这个指针会指向随机的内存空间,可能导致未知的问题。
指针运算
尽管指针变量内记录的是内存地址,但仍可以进行基础的数学计算。
指针运算是对指针的基础型操作,非常适合操纵数组并配合做动态内存分配。
#include "iostream"
using namespace std;
int main(){
// 初始化一个整数数组
int array[] = {1,2,3,4,5};
// 获取数组中索引为2的元素的地址赋值给指针p
int *p = &array[2];
// 通过指针p加上偏移量2来访问数组中索引为4的元素
cout << *(p + 2) << endl; // 5
return 0;
}
动态内存管理
动态内存分配:即由程序员手动的进行内存空间的分配、内存空间的释放等内存管理操作。
C++代码中,变量、数组等对象的创建,是由C++自动分配内存的,称之为(自动)静态内存分配。
(自动)静态内存管理,是不会进行内存空间的自动清理的。(无垃圾回收机制)
我们需要手动的管理内存,即手动分配,用完清理。
#include "iostream"
using namespace std;
int main(){
// 动态分配一个整数类型的内存空间(4字节)
int *p = new int;
// 在分配的内存空间中存储值10
*p = 10;
// 输出内存空间中存储的值,目的是展示new申请的内存空间的使用情况
cout << "new申请的4字节空间内,存放的是:" << *p << endl;
// 释放之前分配的内存空间,以避免内存泄漏
delete p;
return 0;
}
指针悬挂
所以,总结出两点经验:
- 不要轻易进行指针之间相互赋值
- delete回收空间前,确保此空间100%不再被使用
#include "iostream"
using namespace std;
int main(){
int * p1 = new int;
*p1 = 10;
int * p2 = p1; // 指针之间相互赋值
cout << "p1指针指向的内存区域的值是:" << *p1 << endl;
delete p1;
cout << "p2指针指向的内存区域的值是:" << *p2 << endl;
return 0;
}
常量指针
const指针:表示指针本身不可更改,但指向的数据可以更改。
1.7 数组元素的移除
C++内置并未提供对数组元素进行增加(插入)、移除的功能,需要手动实现(vector容器提供,后续学习)。
#include "iostream"
using namespace std;
int main(){
int * pArr = new int[5] {1, 2, 3, 4, 5};
// 创建一个新的数组,将需要保留的复制到新数组中
int * pNewArr = new int[4];
// 循环去遍历老的数组,将需要保留的元素复制到新数组中
for(int i = 0; i < 5; i++){
if (i == 2) {
continue;
}
if (i > 2) {
pNewArr[i - 1] = pArr[i];
} else {
pNewArr[i] = pArr[i];
}
}
delete [] pArr; // 回收老数组
// 循环打印新数组
for(int i = 0; i < 4; i++){
cout << pNewArr[i] << endl;
}
return 0;
}
1.8 数组元素的插入
#include "iostream"
using namespace std;
int main(){
// 需求:将元素分别插入下标1和3的位置
int * pArr = new int[5] {1, 2, 3, 4, 5};
// 创建一个新的数组
int * pNewArr = new int[7];
int offset = 0; // 偏移量用来控制新老数组元素的下标对照
// 循环新数组,挨个进行元素填充
for(int i = 0; i < 7; i++){
if (i == 1) {
pNewArr[i] = 11; // 插入新元素
offset++;
continue;
} else if (i == 3) {
pNewArr[i] = 66; // 插入新元素
offset++;
continue;
}
// 不是插入位置,从老数组中提取元素放入新数组中
// 公式:老数组的元素下标 + offset = 新数组的元素下标
// 当前循环的i是新数组的下标
pNewArr[i] = pArr[i - offset];
}
delete [] pArr;
// 遍历新数组
for(int i = 0; i < 7; i++){
cout << pNewArr[i] << " ";
}
return 0;
}
标签:cout,int,元素,笔记,C++,数组,array,指针
From: https://blog.csdn.net/qq_38196449/article/details/142004468