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++编程的基础技能,为后续学习容器和算法打下坚实基础。