C++ 数组笔记

3 阅读5分钟

获取数组长度和大小

在C++中,获取数组长度(元素个数)和大小(内存占用量)的方法取决于数组类型和上下文。

1. 内置数组(C风格数组)

在同一作用域内获取

#include <iostream>
using namespace std;

int main() {
    // 定义数组
    int numbers[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
    
    // 方法1:使用sizeof运算符
    int length1 = sizeof(numbers) / sizeof(numbers[0]);
    size_t size1 = sizeof(numbers);  // 字节数
    
    cout << "方法1 - 数组长度: " << length1 << endl;
    cout << "方法1 - 数组大小: " << size1 << " 字节" << endl;
    
    // 方法2:使用模板函数(更安全)
    template<typename T, size_t N>
    size_t getArrayLength(T (&arr)[N]) {
        return N;
    }
    
    size_t length2 = getArrayLength(numbers);
    cout << "方法2 - 数组长度: " << length2 << endl;
    
    // 方法3:C++17结构化绑定(需要知道具体元素)
    auto [a, b, c, d, e, f, g, h, i, j] = numbers;
    cout << "方法3 - 数组长度: " << 10 << endl;
    
    return 0;
}

在不同作用域(函数参数)中获取

当数组作为函数参数传递时,它会退化为指针,失去大小信息:

#include <iostream>
using namespace std;

// 错误示例:无法获取数组长度
void printArrayWrong(int arr[]) {
    // 错误!这里arr是指针,不是数组
    // int length = sizeof(arr) / sizeof(arr[0]); // 错误!
    cout << "sizeof(arr) = " << sizeof(arr) << endl; // 输出指针大小
}

// 正确方法1:传递大小参数
void printArray1(int arr[], int size) {
    for (int i = 0; i < size; i++) {
        cout << arr[i] << " ";
    }
    cout << endl;
}

// 正确方法2:使用模板(保留数组类型信息)
template<typename T, size_t N>
void printArray2(T (&arr)[N]) {
    cout << "数组长度: " << N << endl;
    for (size_t i = 0; i < N; i++) {
        cout << arr[i] << " ";
    }
    cout << endl;
}

// 正确方法3:使用指针和结束标志
void printArray3(int* begin, int* end) {
    int length = end - begin;
    cout << "数组长度: " << length << endl;
    for (int* p = begin; p != end; p++) {
        cout << *p << " ";
    }
    cout << endl;
}

int main() {
    int arr[] = {1, 2, 3, 4, 5};
    
    // 方法1:传递大小
    printArray1(arr, sizeof(arr)/sizeof(arr[0]));
    
    // 方法2:使用模板
    printArray2(arr);
    
    // 方法3:使用指针范围
    printArray3(arr, arr + sizeof(arr)/sizeof(arr[0]));
    
    return 0;
}

2. std::array(C++11)

std::array提供了直接获取长度和大小的方法:

#include <iostream>
#include <array>
using namespace std;

int main() {
    array<int, 5> arr = {1, 2, 3, 4, 5};
    
    // 获取元素个数
    cout << "元素个数: " << arr.size() << endl;
    cout << "元素个数: " << arr.max_size() << endl; // 与size()相同
    
    // 获取字节大小
    cout << "总字节数: " << sizeof(arr) << endl;
    cout << "元素大小: " << sizeof(arr[0]) << endl;
    cout << "计算长度: " << sizeof(arr) / sizeof(arr[0]) << endl;
    
    // 使用empty()检查是否为空
    cout << "是否为空: " << (arr.empty() ? "是" : "否") << endl;
    
    // 使用范围for循环遍历
    for (int num : arr) {
        cout << num << " ";
    }
    cout << endl;
    
    return 0;
}

3. 多维数组

#include <iostream>
using namespace std;

int main() {
    // 二维数组
    int matrix[3][4] = {
        {1, 2, 3, 4},
        {5, 6, 7, 8},
        {9, 10, 11, 12}
    };
    
    // 获取总大小
    cout << "总字节数: " << sizeof(matrix) << endl; // 3*4*4 = 48
    
    // 获取行数
    int rows = sizeof(matrix) / sizeof(matrix[0]);
    cout << "行数: " << rows << endl;
    
    // 获取列数
    int cols = sizeof(matrix[0]) / sizeof(matrix[0][0]);
    cout << "列数: " << cols << endl;
    
    // 获取元素总数
    int totalElements = sizeof(matrix) / sizeof(matrix[0][0]);
    cout << "元素总数: " << totalElements << endl;
    
    // 遍历多维数组
    for (int i = 0; i < rows; i++) {
        for (int j = 0; j < cols; j++) {
            cout << matrix[i][j] << " ";
        }
        cout << endl;
    }
    
    return 0;
}

4. 动态数组

对于动态分配的数组,sizeof无法获取实际长度,需要手动跟踪:

#include <iostream>
using namespace std;

int main() {
    // 动态分配数组
    int size = 10;
    int* dynamicArray = new int[size];
    
    // 填充数组
    for (int i = 0; i < size; i++) {
        dynamicArray[i] = i * 10;
    }
    
    // sizeof只能获取指针大小,不能获取数组大小
    cout << "指针大小: " << sizeof(dynamicArray) << " 字节" << endl; // 通常8字节
    cout << "单个元素大小: " << sizeof(dynamicArray[0]) << " 字节" << endl;
    
    // 无法通过sizeof获取动态数组长度!
    // 必须手动跟踪大小
    
    // 正确:传递大小参数
    for (int i = 0; i < size; i++) {
        cout << dynamicArray[i] << " ";
    }
    cout << endl;
    
    delete[] dynamicArray; // 不要忘记释放内存
    
    return 0;
}

5. 实用模板函数

创建通用工具函数来处理数组:

#include <iostream>
#include <type_traits>
using namespace std;

// 获取数组长度的模板函数
template<typename T, size_t N>
constexpr size_t arrayLength(T (&)[N]) {
    return N;
}

// 安全打印数组的模板函数
template<typename T>
void printArray(T* arr, size_t size) {
    cout << "数组长度: " << size << endl;
    cout << "数组内容: ";
    for (size_t i = 0; i < size; i++) {
        cout << arr[i] << " ";
    }
    cout << endl;
}

// 获取数组大小(字节数)的模板函数
template<typename T, size_t N>
constexpr size_t arraySize(T (&arr)[N]) {
    return sizeof(arr);
}

int main() {
    int intArray[] = {1, 2, 3, 4, 5};
    double doubleArray[] = {1.1, 2.2, 3.3, 4.4};
    
    cout << "intArray长度: " << arrayLength(intArray) << endl;
    cout << "intArray大小: " << arraySize(intArray) << " 字节" << endl;
    
    cout << "doubleArray长度: " << arrayLength(doubleArray) << endl;
    cout << "doubleArray大小: " << arraySize(doubleArray) << " 字节" << endl;
    
    printArray(intArray, arrayLength(intArray));
    
    return 0;
}

6. 获取字符串数组长度

对于字符串数组(C风格字符串):

#include <iostream>
#include <cstring> // 用于strlen
using namespace std;

int main() {
    // C风格字符串
    char str1[] = "Hello";
    char str2[] = {'H', 'e', 'l', 'l', 'o', '\0'};
    
    // 方法1:sizeof(包括null终止符)
    cout << "str1 sizeof: " << sizeof(str1) << endl; // 6
    cout << "str2 sizeof: " << sizeof(str2) << endl; // 6
    
    // 方法2:strlen(不包括null终止符)
    cout << "str1 strlen: " << strlen(str1) << endl; // 5
    cout << "str2 strlen: " << strlen(str2) << endl; // 5
    
    // 字符串数组
    const char* names[] = {"Alice", "Bob", "Charlie", "David"};
    
    // 获取字符串数组的长度
    int nameCount = sizeof(names) / sizeof(names[0]);
    cout << "名字数量: " << nameCount << endl;
    
    // 遍历字符串数组
    for (int i = 0; i < nameCount; i++) {
        cout << names[i] << " (长度: " << strlen(names[i]) << ")" << endl;
    }
    
    return 0;
}

总结比较

数组类型获取长度方法获取大小方法注意事项
内置数组sizeof(arr)/sizeof(arr[0])sizeof(arr)在同一作用域内有效
函数参数数组传递大小参数或使用模板无法直接获取数组退化为指针
std::arrayarr.size()sizeof(arr)推荐使用
动态数组手动跟踪大小无法直接获取需要自己管理
字符串数组sizeof(arr)/sizeof(arr[0])sizeof(arr)区分sizeofstrlen

最佳实践建议

  1. 优先使用标准库容器:使用std::array(固定大小)或std::vector(动态大小)代替内置数组
  2. 传递数组时同时传递大小:避免数组退化为指针导致信息丢失
  3. 使用模板函数处理数组:可以保留数组类型信息
  4. 避免在动态数组上使用sizeofsizeof只能获取指针大小,不能获取分配的内存大小
// 推荐做法:使用std::array
#include <array>
#include <iostream>

int main() {
    std::array<int, 5> arr = {1, 2, 3, 4, 5};
    
    // 轻松获取信息
    std::cout << "长度: " << arr.size() << std::endl;
    std::cout << "是否为空: " << arr.empty() << std::endl;
    
    // 安全遍历
    for (auto& element : arr) {
        std::cout << element << " ";
    }
    
    return 0;
}