当前位置: 首页 > news >正文

数组基础及原理

C++数组是相同类型元素的有序集合,具有固定大小,是C++中最基础的数据结构之一

一、数组的定义

数组的核心特征是相同类型固定大小,定义格式为:
元素类型 数组名[元素个数];

1. 一维数组定义
int arr1[5];  // 定义一个包含5个int类型元素的数组
double arr2[10];  // 定义一个包含10个double类型元素的数组
char arr3[3];  // 定义一个包含3个char类型元素的数组
  • 元素个数必须是编译期常量(C++11前必须是字面量或const变量,C++11后支持constexpr)。
  • 数组名是一个常量指针(不能被赋值,如arr1 = arr2;是错误的)。
2. 多维数组定义

多维数组本质是“数组的数组”,最常用的是二维数组,定义格式:
元素类型 数组名[第一维大小][第二维大小]...;

int matrix[2][3];  // 2行3列的二维int数组(本质是:包含2个元素的数组,每个元素是"3个int的数组")
double cube[2][2][2];  // 三维double数组(2×2×2)

二、数组的初始化

数组可以在定义时初始化,未初始化的全局/静态数组会被自动初始化为0,局部数组(栈上)则是随机值。

1. 一维数组初始化
  • 完全初始化:显式指定所有元素

    int arr[3] = {1, 2, 3};  // 元素依次为1,2,3
    
  • 部分初始化:未指定的元素自动为0

    int arr[5] = {1, 2};  // 元素为1,2,0,0,0
    
  • 省略大小初始化:编译器根据初始化列表长度自动推断大小

    int arr[] = {1, 2, 3, 4};  // 自动推断大小为4
    
  • 字符数组初始化(字符串特殊处理):
    字符串会自动添加终止符'\0',因此初始化时需预留位置:

    char str1[6] = {'h', 'e', 'l', 'l', 'o'};  // 需手动加'\0',否则不是字符串
    char str2[] = "hello";  // 自动包含'\0',大小为6('h','e','l','l','o','\0')
    
2. 多维数组初始化
  • 二维数组初始化:用嵌套大括号按行初始化

    int matrix[2][3] = {{1, 2, 3},  // 第一行{4, 5, 6}   // 第二行
    };
    
  • 部分初始化:未指定的元素自动为0

    int matrix[2][3] = {{1}, {4, 5}};  // 结果:{{1,0,0}, {4,5,0}}
    
  • 省略第一维大小:编译器根据初始化列表推断第一维长度

    int matrix[][] = {{1,2}, {3,4}, {5,6}};  // 错误:只能省略第一维
    int matrix[][2] = {{1,2}, {3,4}, {5,6}};  // 正确:第一维自动推断为3
    

三、数组的访问方式

数组元素通过下标指针访问,下标从0开始(即第一个元素下标为0,最后一个为n-1n为元素个数)。

1. 下标访问(最常用)

格式:数组名[下标]

int arr[3] = {10, 20, 30};
cout << arr[0];  // 访问第一个元素,输出10
arr[1] = 200;    // 修改第二个元素为200
  • 多维数组通过多个下标访问:
    int matrix[2][3] = {{1,2,3}, {4,5,6}};
    cout << matrix[1][2];  // 访问第二行第三列元素,输出6
    
2. 指针访问

数组名会隐式转换为指向首元素的指针(除作为sizeof&的操作数外),因此可通过指针偏移访问元素:

int arr[3] = {10, 20, 30};
int* p = arr;  // 等价于int* p = &arr[0]cout << *p;       // 访问首元素(arr[0]),输出10
cout << *(p + 1); // 访问第二个元素(arr[1]),输出20
  • 多维数组的指针访问:
    二维数组int matrix[2][3]中,matrix是指向“包含3个int的数组”的指针,matrix + i指向第i行,*(matrix + i) + j指向第i行第j列元素:
    cout << *(*(matrix + 1) + 2);  // 等价于matrix[1][2],输出6
    
注意:下标越界问题

C++不检查数组下标是否越界(编译通过,运行时未定义行为),越界访问可能修改其他内存数据,导致程序崩溃:

int arr[3] = {1,2,3};
cout << arr[5];  // 越界访问,结果随机(危险!)

四、数组的内存布局

数组在内存中是连续存储的,所有元素占用一段连续的内存空间,这是数组的核心特性。

1. 一维数组的内存布局

假设int arr[3] = {1,2,3}(int占4字节),内存布局如下:

arr[0] → 地址0x1000(值1)
arr[1] → 地址0x1004(值2)  // 与前一个元素相差4字节(int大小)
arr[2] → 地址0x1008(值3)  // 与前一个元素相差4字节
  • 相邻元素地址差 = 元素类型大小(可通过sizeof(arr[0])获取)。
  • 数组总大小 = 元素个数 × 元素类型大小(sizeof(arr) = 3×4 = 12字节)。
2. 多维数组的内存布局

多维数组同样是连续存储的,按“行优先”(先存完一行再存下一行)排列。

int matrix[2][3] = {{1,2,3}, {4,5,6}}为例,内存布局如下:

matrix[0][0] → 0x2000(1)
matrix[0][1] → 0x2004(2)
matrix[0][2] → 0x2008(3)
matrix[1][0] → 0x200C(4)  // 紧跟第一行最后一个元素
matrix[1][1] → 0x2010(5)
matrix[1][2] → 0x2014(6)
  • 多维数组可看作“展开的一维数组”,matrix[1][0]的地址 = matrix[0][2]的地址 + 4字节。
3. 不同存储位置的数组
  • 栈上的数组(局部数组):在函数内定义,生命周期随函数结束而销毁,大小固定。
  • 堆上的数组(动态数组):用new[]分配,需手动delete[]释放,大小可在运行时指定:
    int n = 5;
    int* arr = new int[n];  // 运行时确定大小(堆上)
    delete[] arr;  // 必须释放,否则内存泄漏
    
  • 全局/静态数组:在函数外或用static修饰,生命周期与程序一致,自动初始化为0。

总结

  • 数组是固定大小的相同类型元素集合,定义时需指定类型和大小。
  • 初始化支持完全、部分、省略大小等方式,字符数组需注意'\0'
  • 访问通过下标或指针,需避免越界。
  • 内存连续存储(一维/多维均如此),栈上数组大小固定,堆上数组大小可动态指定。

掌握数组的特性对理解更复杂的数据结构(如字符串、容器)至关重要。

数组的基本操作:

1. 数组初始化

数组初始化是创建数组并为其元素赋初始值的过程,常见方式有以下几种:

// 方法1:声明时完全初始化
int arr1[5] = {1, 2, 3, 4, 5};  // 定义包含5个int元素的数组并初始化// 方法2:部分初始化(剩余元素自动为0)
int arr2[5] = {1, 2};  // 前两个元素为1、2,后三个元素自动为0// 方法3:不指定大小,由初始化列表自动推断
int arr3[] = {10, 20, 30};  // 编译器自动推断数组大小为3// 方法4:字符数组初始化(字符串)
char str1[] = "hello";  // 自动包含终止符'\0',长度为6
char str2[6] = {'h', 'i', '\0'};  // 显式添加终止符

注意:数组大小必须是编译时常量,不能是变量。

2. 数组赋值

数组赋值包括给空数组元素赋值和修改已有元素的值:

// 给空数组赋值
int nums[4];
for (int i = 0; i < 4; i++) {nums[i] = i * 2;  // 逐个元素赋值:0, 2, 4, 6
}// 修改数组元素
nums[2] = 100;  // 将索引2的元素改为100,数组变为:0, 2, 100, 6// 字符数组赋值
char name[10];
name[0] = 'J';
name[1] = 'o';
name[2] = 'h';
name[3] = 'n';
name[4] = '\0';  // 字符串必须以'\0'结尾

注意:C++不支持数组整体赋值(如arr1 = arr2是错误的),必须逐个元素赋值。

3. 数组遍历

遍历是按顺序访问数组中的每个元素,常用方法有:

int scores[] = {85, 92, 78, 90};
int length = sizeof(scores) / sizeof(scores[0]);  // 计算数组长度// 方法1:传统for循环(通过索引访问)
cout << "传统for循环遍历:";
for (int i = 0; i < length; i++) {cout << scores[i] << " ";
}// 方法2:范围for循环(C++11及以上,更简洁)
cout << "\n范围for循环遍历:";
for (int score : scores) {  // 自动迭代每个元素cout << score << " ";
}

技巧:sizeof(数组名)/sizeof(数组元素)是计算数组长度的常用方式。

4. 查找元素

查找元素是在数组中寻找特定值或满足条件的元素,主要方法有:

int arr[] = {15, 30, 25, 40, 30};
int len = sizeof(arr) / sizeof(arr[0]);
int target = 30;// 方法1:线性查找(手动实现)
int findIndex(int arr[], int length, int target) {for (int i = 0; i < length; i++) {if (arr[i] == target) {return i;  // 找到返回索引}}return -1;  // 未找到返回-1
}int index = findIndex(arr, len, target);
if (index != -1) {cout << "找到元素" << target << ",索引为:" << index;
} else {cout << "未找到元素" << target;
}// 方法2:使用标准库函数find(需包含<algorithm>)
#include <algorithm>
int* found = find(arr, arr + len, target);
if (found != arr + len) {  // 判断是否找到cout << "\n找到元素,索引为:" << (found - arr);
}// 方法3:查找满足条件的元素
int findGreater(int arr[], int length, int value) {for (int i = 0; i < length; i++) {if (arr[i] > value) {return i;  // 返回第一个大于value的元素索引}}return -1;
}

注意事项

  1. 数组索引从0开始,最大索引为数组长度-1,访问越界会导致未定义行为。
  2. 数组大小固定,一旦声明无法改变,若需动态大小可使用vector容器。
  3. 数组名本质上是指向首元素的指针,作为函数参数时会退化为指针,丢失长度信息。

掌握这些基本操作是使用C++数组的基础,在实际开发中,根据需求选择合适的方法可以提高代码效率和可读性。

http://www.dtcms.com/a/361888.html

相关文章:

  • 秋招冲刺计划(Day12)
  • Qwen-Image-Edit完全指南:实战20B参数模型的文字与语义-外观双重编辑
  • 如何使用VMware创建一台Ubuntu机器
  • Linux内核内存管理系列博客教程学习规划
  • KVM虚拟机快速安装与配置指南
  • leetcode算法day24
  • 安科瑞能源管理系统支撑低碳园区节能降碳发展
  • 【前端:Html】--4.进阶:媒体
  • K8S 知识框架和命令操作
  • 刷题之链表oj题目
  • 学习JavaScript的第一个简单程序:Hello World
  • Vue3响应式陷阱:如何避免ref解构导致的响应式丢失
  • ansible知识点总结1
  • Rviz-Gazebo联动
  • C++ 类型系统浅析:值类别与引用类型
  • 工业飞拍技术:高速生产线的 “动态抓拍神器”,到底牛在哪?
  • Java面试宝典:Redis高并发高可用(主从复制、哨兵)
  • oracle默认事务隔离级别
  • ArcGIS 4.x 绘图
  • 开源 C++ QT Widget 开发(十)IPC进程间通信--共享内存
  • 164.在 Vue3 中使用 OpenLayers 加载 Esri 地图(多种形式)
  • Python核心技术开发指南(033)——函数的嵌套
  • matlab扫雷小游戏
  • 计算机组成原理易混知识点
  • Python3环境搭建教程 - 使用Conda工具
  • Chrome 如何清除浏览器缓存
  • MinerU环境部署
  • (Arxiv-2025)HunyuanCustom:一种面向多模态驱动的定制化视频生成架构
  • Cesium 加载桥梁3DTiles数据时,出现部分区域发暗、部分正常的现象
  • 汽车曲柄连杆机构cad+ea113+设计说明书