Skip to content

C++ 数组

概述

数组是C++中用于存储相同类型多个元素的基本数据结构。数组提供连续的内存存储和高效的随机访问能力。本章介绍一维数组、多维数组以及现代C++的数组替代方案。

📊 一维数组

数组声明和初始化

cpp
#include <iostream>

int main() {
    std::cout << "=== 数组声明和初始化 ===" << std::endl;
    
    // 1. 基本声明和初始化
    int arr1[5] = {1, 2, 3, 4, 5};           // 完整初始化
    int arr2[5] = {10, 20};                  // 部分初始化,其余为0
    int arr3[] = {100, 200, 300};            // 自动推导大小
    int arr4[5] = {};                        // 零初始化
    
    // 2. 数组大小和访问
    int size = sizeof(arr1) / sizeof(arr1[0]);
    std::cout << "数组大小: " << size << std::endl;
    std::cout << "第一个元素: " << arr1[0] << std::endl;
    std::cout << "最后一个元素: " << arr1[4] << std::endl;
    
    // 3. 遍历数组
    std::cout << "所有元素: ";
    for (int i = 0; i < size; i++) {
        std::cout << arr1[i] << " ";
    }
    std::cout << std::endl;
    
    // 4. 范围for循环 (C++11)
    std::cout << "范围for: ";
    for (int num : arr1) {
        std::cout << num << " ";
    }
    std::cout << std::endl;
    
    return 0;
}

数组作为函数参数

cpp
#include <iostream>

// 数组作为参数(实际传递指针)
void printArray(int arr[], int size) {
    for (int i = 0; i < size; i++) {
        std::cout << arr[i] << " ";
    }
    std::cout << std::endl;
}

// 修改数组元素
void doubleArray(int arr[], int size) {
    for (int i = 0; i < size; i++) {
        arr[i] *= 2;
    }
}

// 常量数组参数(只读)
void printReadOnly(const int arr[], int size) {
    for (int i = 0; i < size; i++) {
        std::cout << arr[i] << " ";
        // arr[i] = 0;  // 错误!不能修改const数组
    }
    std::cout << std::endl;
}

int main() {
    std::cout << "=== 数组作为函数参数 ===" << std::endl;
    
    int data[5] = {1, 2, 3, 4, 5};
    
    std::cout << "原始数组: ";
    printArray(data, 5);
    
    doubleArray(data, 5);
    std::cout << "翻倍后: ";
    printArray(data, 5);
    
    std::cout << "只读访问: ";
    printReadOnly(data, 5);
    
    return 0;
}

🎯 多维数组

二维数组

cpp
#include <iostream>
#include <iomanip>

int main() {
    std::cout << "=== 二维数组 ===" << std::endl;
    
    // 1. 声明和初始化
    int matrix[3][4] = {
        {1, 2, 3, 4},
        {5, 6, 7, 8},
        {9, 10, 11, 12}
    };
    
    // 2. 访问和修改
    std::cout << "matrix[1][2] = " << matrix[1][2] << std::endl;
    matrix[0][0] = 100;
    
    // 3. 遍历二维数组
    std::cout << "完整矩阵:" << std::endl;
    for (int i = 0; i < 3; i++) {
        for (int j = 0; j < 4; j++) {
            std::cout << std::setw(4) << matrix[i][j];
        }
        std::cout << std::endl;
    }
    
    // 4. 使用范围for循环
    std::cout << "使用范围for:" << std::endl;
    for (const auto& row : matrix) {
        for (int element : row) {
            std::cout << std::setw(4) << element;
        }
        std::cout << std::endl;
    }
    
    // 5. 计算矩阵维度
    int rows = sizeof(matrix) / sizeof(matrix[0]);
    int cols = sizeof(matrix[0]) / sizeof(matrix[0][0]);
    std::cout << "矩阵大小: " << rows << "x" << cols << std::endl;
    
    return 0;
}

二维数组操作

cpp
#include <iostream>

// 矩阵运算函数
void printMatrix(int matrix[][3], int rows) {
    for (int i = 0; i < rows; i++) {
        for (int j = 0; j < 3; j++) {
            std::cout << matrix[i][j] << " ";
        }
        std::cout << std::endl;
    }
}

void addMatrices(int a[][3], int b[][3], int result[][3], int rows) {
    for (int i = 0; i < rows; i++) {
        for (int j = 0; j < 3; j++) {
            result[i][j] = a[i][j] + b[i][j];
        }
    }
}

int main() {
    std::cout << "=== 矩阵运算 ===" << std::endl;
    
    int matrixA[2][3] = {{1, 2, 3}, {4, 5, 6}};
    int matrixB[2][3] = {{7, 8, 9}, {10, 11, 12}};
    int result[2][3];
    
    std::cout << "矩阵A:" << std::endl;
    printMatrix(matrixA, 2);
    
    std::cout << "矩阵B:" << std::endl;
    printMatrix(matrixB, 2);
    
    addMatrices(matrixA, matrixB, result, 2);
    std::cout << "A + B:" << std::endl;
    printMatrix(result, 2);
    
    return 0;
}

🔍 字符数组

C风格字符串

cpp
#include <iostream>
#include <cstring>

int main() {
    std::cout << "=== C风格字符串 ===" << std::endl;
    
    // 1. 字符数组初始化
    char str1[] = "Hello";          // 自动添加'\0'
    char str2[10] = "World";        // 指定大小
    char str3[6] = {'H','e','l','l','o','\0'};  // 手动指定
    
    std::cout << "str1: " << str1 << std::endl;
    std::cout << "str2: " << str2 << std::endl;
    
    // 2. 字符串长度
    std::cout << "str1长度: " << strlen(str1) << std::endl;
    
    // 3. 字符串操作
    char destination[20];
    strcpy(destination, str1);      // 复制
    strcat(destination, " ");       // 连接
    strcat(destination, str2);
    
    std::cout << "连接结果: " << destination << std::endl;
    
    // 4. 字符串比较
    int cmp = strcmp(str1, "Hello");
    std::cout << "字符串比较: " << (cmp == 0 ? "相等" : "不等") << std::endl;
    
    // 5. 逐字符访问
    std::cout << "逐字符输出: ";
    for (int i = 0; str1[i] != '\0'; i++) {
        std::cout << str1[i] << " ";
    }
    std::cout << std::endl;
    
    return 0;
}

🚀 现代C++数组:std::array

std::array基本用法

cpp
#include <iostream>
#include <array>
#include <algorithm>

int main() {
    std::cout << "=== std::array (C++11) ===" << std::endl;
    
    // 1. 声明和初始化
    std::array<int, 5> arr1 = {1, 2, 3, 4, 5};
    std::array<int, 5> arr2{10, 20, 30, 40, 50};
    std::array<int, 5> arr3{};  // 零初始化
    
    // 2. 基本操作
    std::cout << "数组大小: " << arr1.size() << std::endl;
    std::cout << "第一个元素: " << arr1.front() << std::endl;
    std::cout << "最后一个元素: " << arr1.back() << std::endl;
    
    // 3. 安全访问
    std::cout << "arr1[2]: " << arr1[2] << std::endl;
    std::cout << "arr1.at(2): " << arr1.at(2) << std::endl;  // 边界检查
    
    // 4. 遍历
    std::cout << "所有元素: ";
    for (const auto& element : arr1) {
        std::cout << element << " ";
    }
    std::cout << std::endl;
    
    // 5. 算法库支持
    std::sort(arr2.begin(), arr2.end(), std::greater<int>());
    std::cout << "降序排列: ";
    for (int val : arr2) std::cout << val << " ";
    std::cout << std::endl;
    
    // 6. 查找元素
    auto found = std::find(arr1.begin(), arr1.end(), 3);
    if (found != arr1.end()) {
        std::cout << "找到元素3" << std::endl;
    }
    
    // 7. 数组比较
    std::array<int, 5> arr4 = {1, 2, 3, 4, 5};
    std::cout << "arr1 == arr4: " << (arr1 == arr4) << std::endl;
    
    return 0;
}

数组类型比较

cpp
#include <iostream>
#include <array>
#include <vector>

int main() {
    std::cout << "=== 数组类型比较 ===" << std::endl;
    
    // 1. 三种数组类型
    int raw_array[5] = {1, 2, 3, 4, 5};
    std::array<int, 5> std_array = {1, 2, 3, 4, 5};
    std::vector<int> vector_array = {1, 2, 3, 4, 5};
    
    // 2. 大小获取
    std::cout << "原生数组大小: " << sizeof(raw_array)/sizeof(raw_array[0]) << std::endl;
    std::cout << "std::array大小: " << std_array.size() << std::endl;
    std::cout << "std::vector大小: " << vector_array.size() << std::endl;
    
    // 3. 边界检查
    std::cout << "\n边界检查测试:" << std::endl;
    try {
        std::cout << "std::array安全访问: " << std_array.at(4) << std::endl;
        // std_array.at(10);  // 会抛出异常
    } catch (const std::out_of_range& e) {
        std::cout << "捕获边界异常: " << e.what() << std::endl;
    }
    
    // 4. 动态调整(只有vector支持)
    vector_array.push_back(6);
    std::cout << "vector添加元素后大小: " << vector_array.size() << std::endl;
    
    // 5. 选择指南
    std::cout << "\n=== 选择指南 ===" << std::endl;
    std::cout << "固定大小,类型安全 -> std::array" << std::endl;
    std::cout << "动态大小,灵活使用 -> std::vector" << std::endl;
    std::cout << "与C代码兼容 -> 原生数组" << std::endl;
    std::cout << "极致性能要求 -> 原生数组" << std::endl;
    
    return 0;
}

📋 数组最佳实践

安全数组操作

cpp
#include <iostream>
#include <array>
#include <algorithm>

// 数组工具函数
template<typename T, size_t N>
void printArray(const std::array<T, N>& arr, const std::string& name) {
    std::cout << name << ": ";
    for (const auto& element : arr) {
        std::cout << element << " ";
    }
    std::cout << std::endl;
}

// 查找最大值
template<typename T, size_t N>
size_t findMaxIndex(const std::array<T, N>& arr) {
    auto max_it = std::max_element(arr.begin(), arr.end());
    return std::distance(arr.begin(), max_it);
}

int main() {
    std::cout << "=== 数组最佳实践 ===" << std::endl;
    
    std::array<int, 8> scores = {85, 92, 78, 96, 88, 79, 94, 87};
    
    printArray(scores, "学生成绩");
    
    // 统计操作
    size_t maxIndex = findMaxIndex(scores);
    std::cout << "最高分: " << scores[maxIndex] << " (位置: " << maxIndex << ")" << std::endl;
    
    // 计算平均分
    int sum = 0;
    for (int score : scores) {
        sum += score;
    }
    double average = static_cast<double>(sum) / scores.size();
    std::cout << "平均分: " << average << std::endl;
    
    // 排序和查找
    auto sortedScores = scores;
    std::sort(sortedScores.begin(), sortedScores.end());
    printArray(sortedScores, "排序后");
    
    // 统计及格人数
    int passCount = std::count_if(scores.begin(), scores.end(), 
                                 [](int score) { return score >= 80; });
    std::cout << "及格人数 (>=80): " << passCount << std::endl;
    
    return 0;
}

常见错误避免

cpp
#include <iostream>
#include <array>

int main() {
    std::cout << "=== 避免常见错误 ===" << std::endl;
    
    // 1. 越界访问
    std::array<int, 5> arr = {1, 2, 3, 4, 5};
    
    // 安全访问
    try {
        std::cout << "安全访问arr[4]: " << arr.at(4) << std::endl;
        // arr.at(10);  // 会抛出异常
    } catch (const std::out_of_range& e) {
        std::cout << "越界访问被捕获" << std::endl;
    }
    
    // 2. 使用size()而非硬编码
    std::cout << "正确的遍历方式:" << std::endl;
    for (size_t i = 0; i < arr.size(); i++) {
        std::cout << arr[i] << " ";
    }
    std::cout << std::endl;
    
    // 3. const正确性
    const auto& readOnlyArray = arr;
    // readOnlyArray[0] = 100;  // 错误!
    std::cout << "只读访问: " << readOnlyArray[0] << std::endl;
    
    return 0;
}

总结

C++数组提供了高效的数据存储和访问机制:

数组类型选择

类型适用场景优点缺点
原生数组C兼容,高性能最小开销无边界检查
std::array固定大小,类型安全现代C++特性编译时确定大小
std::vector动态大小灵活性好额外内存开销

核心要点

  • 声明初始化:多种初始化方式,注意数组大小
  • 多维数组:矩阵操作和复杂数据结构
  • 函数参数:数组参数退化为指针
  • 现代替代:std::array提供更好的类型安全

最佳实践

  • 优先使用std::array而非原生数组
  • 使用at()方法进行边界检查
  • 避免硬编码数组大小
  • 合理选择数组类型
  • 注意const正确性

掌握数组使用是C++编程的基础技能,为后续学习容器和算法打下坚实基础。

本站内容仅供学习和研究使用。