C++ 数组详解:从基础到实战

一、数组的定义与核心特性

(一)什么是数组?

数组(Array)是 C++ 中用于存储一组相同类型元素的连续内存空间。它通过一个统一的名称(数组名)和索引(下标)来访问每个元素,是实现批量数据管理的基础工具。

(二)核心特性

特性 说明
同类型 所有元素必须是同一数据类型(如intdouble
连续性 元素在内存中连续存放,地址递增(&arr [i+1] = &arr [i] + sizeof (类型))
固定大小 数组声明时需指定长度(C++ 标准中不允许动态调整,vector可替代)
索引访问 从 0 开始计数(第一个元素为arr[0],第 n 个元素为arr[n-1]

二、数组的声明与初始化

(一)基础声明语法

cpp

类型 数组名[数组长度]; // 声明一个未初始化的数组

  • 类型:可以是基本类型(如int)、自定义类型(如struct)。
  • 数组名:遵循变量命名规则(字母 / 数字 / 下划线,不能以数字开头)。
  • 数组长度:必须是常量表达式(C++11 前不支持变量),表示数组能存储的元素个数。

(二)初始化方式

1. 静态初始化(声明时赋值)

cpp

// 完全初始化:元素个数与声明长度一致
int scores[5] = {90, 85, 92, 78, 88}; 

// 部分初始化:未显式赋值的元素自动设为0(仅适用于全局/静态数组)
double prices[4] = {19.9, 29.9}; // 等价于 {19.9, 29.9, 0.0, 0.0}

// 省略长度:根据初始化列表自动推导长度(推荐新手使用)
char letters[] = {'A', 'B', 'C'}; // 长度为3
2. C++11 列表初始化(更安全)

cpp

// 大括号初始化(可省略等号)
int arr[]{1, 2, 3}; // 等价于int arr[3] = {1,2,3};

// 零初始化:所有元素设为0
float values[5]{}; // 等价于{0.0, 0.0, 0.0, 0.0, 0.0}
3. 动态数组(堆内存,需手动释放)

cpp

int n = 5;
int* dynamic_arr = new int[n]{1, 2, 3, 4, 5}; // C++11支持初始化
// 使用后需释放
delete[] dynamic_arr; 

三、数组的访问与操作

(一)元素访问

通过数组名[索引]访问,索引范围0 ≤ 索引 < 数组长度

cpp

int arr[3] = {10, 20, 30};
cout << arr[0]; // 输出10(第一个元素)
cout << arr[2]; // 输出30(第三个元素)

(二)数组遍历

1. 传统 for 循环(最常用)

cpp

int nums[4] = {5, 3, 8, 1};
for (int i = 0; i < 4; i++) {
    cout << nums[i] << " "; // 输出5 3 8 1
}
2. 范围 for 循环(C++11,更简洁)

cpp

for (int num : nums) { // 自动遍历每个元素,num是元素的拷贝
    cout << num << " ";
}
3. 指针遍历(理解内存布局)

cpp

int* ptr = nums; // 数组名是首元素地址
for (int i = 0; i < 4; i++) {
    cout << *(ptr + i) << " "; // 等价于nums[i]
}

四、多维数组:数组的数组

(一)二维数组声明与初始化

cpp

// 声明:[行数][列数]
int matrix[2][3]; // 2行3列的二维数组

// 初始化(按行赋值)
int grades[2][3] = {
    {85, 90, 92},  // 第0行
    {78, 88, 95}   // 第1行
};

// 省略行数(自动推导)
int table[][2] = {{1,2}, {3,4}}; // 等价于table[2][2]

(二)二维数组访问

cpp

// 访问第i行第j列元素
cout << grades[1][2]; // 输出第1行第2列的95

(三)内存存储方式

二维数组在内存中按行连续存储。例如grades[2][3]的存储顺序为:
grades[0][0] → grades[0][1] → grades[0][2] → grades[1][0] → grades[1][1] → grades[1][2]

五、数组的常见问题与注意事项

(一)越界访问:新手最易犯的错误

数组索引必须在[0, 长度-1]范围内,否则会导致未定义行为(可能崩溃、输出错误值)。

cpp

int arr[3] = {1, 2, 3};
cout << arr[3]; // 错误!索引3超出范围(数组长度为3,最大索引是2)

(二)数组名的本质:常量指针

数组名是首元素的地址(&arr[0]),但它是常量,不能被重新赋值。

cpp

int arr[3] = {1, 2, 3};
int* p = arr; // 正确:p指向数组首地址
arr = p;      // 错误:数组名是常量,不能被赋值

(三)数组与函数参数:传递的是指针

当数组作为函数参数时,会退化为指针(仅传递首地址),因此需要额外传递数组长度。

cpp

// 错误写法:无法正确获取数组长度
void printArray(int arr[]) {
    cout << sizeof(arr); // 输出8(指针大小,非数组大小)
}

// 正确写法:显式传递长度
void printArray(int arr[], int length) {
    for (int i = 0; i < length; i++) {
        cout << arr[i] << " ";
    }
}

六、数组的应用场景

(一)成绩统计

cpp

// 计算班级平均分(假设10名学生)
int scores[10] = {85, 78, 92, 88, 95, 75, 80, 89, 91, 83};
int sum = 0;
for (int score : scores) {
    sum += score;
}
double average = sum / 10.0;
cout << "平均分:" << average << endl; // 输出85.6

(二)数据排序(冒泡排序)

cpp

void bubbleSort(int arr[], int n) {
    for (int i = 0; i < n-1; i++) {
        for (int j = 0; j < n-i-1; j++) {
            if (arr[j] > arr[j+1]) {
                // 交换元素
                int temp = arr[j];
                arr[j] = arr[j+1];
                arr[j+1] = temp;
            }
        }
    }
}

int main() {
    int nums[] = {5, 3, 8, 1, 2};
    int n = sizeof(nums) / sizeof(nums[0]); // 计算数组长度
    bubbleSort(nums, n);
    for (int num : nums) cout << num << " "; // 输出1 2 3 5 8
    return 0;
}

(三)图像处理(像素存储)

二维数组可用于存储图像的像素值(如灰度图像):

cpp

// 10x10的灰度图像(0-255表示亮度)
unsigned char image[10][10] = {
    {255, 255, ..., 255}, // 白色背景
    // ... 中间像素 ...
    {0, 0, ..., 0}        // 黑色前景
};

七、数组 vs vector:何时选择谁?

特性 数组 vector(动态数组)
大小 固定(声明后不可变) 动态调整(自动扩容)
内存位置 栈(局部数组)或堆(new分配) 堆(自动管理)
初始化 需手动处理(易出错) 提供丰富的初始化方法(如vector v(5, 0)
越界检查 无(需手动保证) 可通过at()方法检查(抛出异常)
性能 略高(无额外开销) 接近数组(现代编译器优化后差异小)

选择建议

  • 若数据量固定且追求极致性能 → 数组
  • 若数据量可能变化或需要方便的操作 → vector(C++ 标准库动态数组)

八、实战:用数组实现学生成绩管理

(一)需求描述

实现一个程序,完成以下功能:

  1. 输入 5 名学生的数学成绩
  2. 计算平均分
  3. 查找最高分
  4. 输出所有成绩

(二)代码实现

cpp

#include 
using namespace std;

int main() {
    const int STUDENT_NUM = 5; // 常量定义数组长度(避免魔法数)
    int scores[STUDENT_NUM];

    // 1. 输入成绩
    cout << "请输入" << STUDENT_NUM << "名学生的数学成绩:" << endl;
    for (int i = 0; i < STUDENT_NUM; i++) {
        cin >> scores[i];
    }

    // 2. 计算平均分
    int sum = 0;
    for (int score : scores) {
        sum += score;
    }
    double average = sum / (double)STUDENT_NUM;

    // 3. 查找最高分
    int max_score = scores[0];
    for (int score : scores) {
        if (score > max_score) {
            max_score = score;
        }
    }

    // 4. 输出结果
    cout << "\n所有成绩:";
    for (int score : scores) {
        cout << score << " ";
    }
    cout << "\n平均分:" << average << endl;
    cout << "最高分:" << max_score << endl;

    return 0;
}

(三)执行示例

plaintext

请输入5名学生的数学成绩:
85 92 78 88 95

所有成绩:85 92 78 88 95 
平均分:87.2
最高分:95

九、总结:数组是数据管理的基石

数组是 C++ 中最基础的数据结构之一,它通过连续内存和索引访问提供了高效的数据管理能力。新手学习数组时需重点掌握:

  • 数组的声明、初始化和访问规则
  • 避免越界访问等常见错误
  • 数组在实际问题中的应用(如统计、排序)

尽管vector等动态结构更灵活,但数组仍是理解内存管理和底层逻辑的重要工具。掌握数组后,你可以更轻松地学习链表、树等复杂数据结构,为后续编程学习打下坚实基础!

你可能感兴趣的:(java,jvm,前端)