C++ 学习杂记01:C++ vector 容器详细

概述

std::vector是 C++ 标准模板库(STL)中最常用的顺序容器,它表示一个动态数组,可以在运行时自动调整大小。vector 提供了对元素的随机访问,支持在尾部高效地添加和删除元素。

头文件

复制代码
#include <vector>

基本特性

  • 动态数组:自动管理内存,可按需增长

  • 连续存储:元素在内存中连续存储,支持随机访问

  • 自动扩容:当容量不足时自动重新分配更大的内存空间

  • RAII:自动管理内存,离开作用域时自动释放

  • 模板类:可以存储任意类型的元素

基本操作

1. 创建和初始化

复制代码
复制代码
复制代码
#include <iostream>
#include <vector>
#include <string>

void create_vector() {
    // 1. 默认构造函数 - 创建空vector
    std::vector<int> vec1;
    
    // 2. 指定初始大小
    std::vector<int> vec2(5);           // 5个元素,默认值0
    std::vector<int> vec3(5, 10);       // 5个元素,每个都是10
    
    // 3. 从初始化列表
    std::vector<int> vec4 = {1, 2, 3, 4, 5};
    std::vector<std::string> vec5 = {"Hello", "World", "C++"};
    
    // 4. 从数组
    int arr[] = {10, 20, 30, 40, 50};
    std::vector<int> vec6(arr, arr + 5);
    
    // 5. 复制构造函数
    std::vector<int> vec7(vec4);
    
    // 6. 从其他vector的部分元素
    std::vector<int> vec8(vec4.begin() + 1, vec4.end() - 1);
    
    // 7. 移动构造函数 (C++11)
    std::vector<int> vec9 = std::move(vec4);
    std::cout << "移动后vec4大小: " << vec4.size() << std::endl;  // 0
    std::cout << "移动后vec9大小: " << vec9.size() << std::endl;  // 5
    
    // 输出验证
    std::cout << "vec2: ";
    for (int n : vec2) std::cout << n << " ";  // 0 0 0 0 0
    std::cout << "\nvec3: ";
    for (int n : vec3) std::cout << n << " ";  // 10 10 10 10 10
    std::cout << "\nvec5: ";
    for (const auto& s : vec5) std::cout << s << " ";  // Hello World C++
    std::cout << "\nvec8: ";
    for (int n : vec8) std::cout << n << " ";  // 2 3 4
    std::cout << std::endl;
}

2. 元素访问

复制代码
复制代码
复制代码
void vector_access() {
    std::vector<int> vec = {10, 20, 30, 40, 50};
    
    // 1. 使用下标运算符[] (不进行边界检查)
    std::cout << "vec[0] = " << vec[0] << std::endl;     // 10
    std::cout << "vec[2] = " << vec[2] << std::endl;     // 30
    
    // 2. 使用at()成员函数 (进行边界检查,越界时抛出异常)
    try {
        std::cout << "vec.at(1) = " << vec.at(1) << std::endl;  // 20
        std::cout << "vec.at(10) = " << vec.at(10) << std::endl; // 抛出异常
    } catch (const std::out_of_range& e) {
        std::cout << "异常: " << e.what() << std::endl;
    }
    
    // 3. 访问第一个和最后一个元素
    std::cout << "第一个元素: " << vec.front() << std::endl;  // 10
    std::cout << "最后一个元素: " << vec.back() << std::endl;  // 50
    
    // 4. 通过data()获取底层数组指针
    int* ptr = vec.data();
    std::cout << "通过指针访问: " << *(ptr + 2) << std::endl;  // 30
    
    // 5. 使用迭代器
    std::cout << "通过迭代器遍历: ";
    for (auto it = vec.begin(); it != vec.end(); ++it) {
        std::cout << *it << " ";
    }
    std::cout << std::endl;
    
    // 6. 范围for循环 (C++11)
    std::cout << "范围for循环: ";
    for (int num : vec) {
        std::cout << num << " ";
    }
    std::cout << std::endl;
    
    // 7. 反向访问
    std::cout << "反向遍历: ";
    for (auto rit = vec.rbegin(); rit != vec.rend(); ++rit) {
        std::cout << *rit << " ";
    }
    std::cout << std::endl;
}

3. 容量和大小操作

复制代码
复制代码
复制代码
void vector_capacity() {
    std::vector<int> vec = {1, 2, 3};
    
    // 1. 获取大小和容量
    std::cout << "当前大小: " << vec.size() << std::endl;          // 3
    std::cout << "当前容量: " << vec.capacity() << std::endl;      // >=3
    std::cout << "最大可能大小: " << vec.max_size() << std::endl;  // 理论最大值
    std::cout << "是否为空: " << std::boolalpha << vec.empty() << std::endl;  // false
    
    // 2. 修改大小
    vec.resize(5);           // 扩大,新增元素初始化为0
    std::cout << "resize(5)后大小: " << vec.size() << std::endl;  // 5
    std::cout << "元素: ";
    for (int n : vec) std::cout << n << " ";  // 1 2 3 0 0
    std::cout << std::endl;
    
    vec.resize(8, 100);      // 扩大,新增元素初始化为100
    std::cout << "resize(8, 100)后: ";
    for (int n : vec) std::cout << n << " ";  // 1 2 3 0 0 100 100 100
    std::cout << std::endl;
    
    vec.resize(3);           // 缩小
    std::cout << "resize(3)后: ";
    for (int n : vec) std::cout << n << " ";  // 1 2 3
    std::cout << std::endl;
    
    // 3. 预留容量 (提高性能)
    std::vector<int> vec2;
    std::cout << "\nvec2初始容量: " << vec2.capacity() << std::endl;
    
    vec2.reserve(100);  // 预留100个元素的空间
    std::cout << "reserve(100)后容量: " << vec2.capacity() << std::endl;
    
    // 4. 缩减容量到合适大小
    vec2.push_back(1);
    vec2.push_back(2);
    std::cout << "添加元素后大小: " << vec2.size() 
              << ", 容量: " << vec2.capacity() << std::endl;
    
    vec2.shrink_to_fit();  // 请求减少容量到合适大小
    std::cout << "shrink_to_fit后容量: " << vec2.capacity() << std::endl;
    
    // 5. 容量增长策略演示
    std::vector<int> vec3;
    std::cout << "\n容量增长演示:" << std::endl;
    for (int i = 0; i < 20; ++i) {
        vec3.push_back(i);
        std::cout << "大小: " << vec3.size() 
                  << ", 容量: " << vec3.capacity() << std::endl;
    }
}

4. 元素修改操作

复制代码
复制代码
复制代码
void vector_modification() {
    std::vector<int> vec = {1, 2, 3, 4, 5};
    
    std::cout << "初始vector: ";
    for (int n : vec) std::cout << n << " ";
    std::cout << std::endl;
    
    // 1. 在末尾添加元素
    vec.push_back(6);
    std::cout << "push_back(6)后: ";
    for (int n : vec) std::cout << n << " ";
    std::cout << std::endl;
    
    // 2. 在末尾删除元素
    vec.pop_back();
    std::cout << "pop_back()后: ";
    for (int n : vec) std::cout << n << " ";
    std::cout << std::endl;
    
    // 3. 在指定位置插入元素
    auto it = vec.begin() + 2;  // 指向第三个元素
    vec.insert(it, 99);
    std::cout << "在位置2插入99后: ";
    for (int n : vec) std::cout << n << " ";  // 1 2 99 3 4 5
    std::cout << std::endl;
    
    // 4. 插入多个相同元素
    vec.insert(vec.begin() + 4, 3, 88);  // 在第4个位置插入3个88
    std::cout << "插入3个88后: ";
    for (int n : vec) std::cout << n << " ";  // 1 2 99 3 88 88 88 4 5
    std::cout << std::endl;
    
    // 5. 插入一个范围
    std::vector<int> other = {100, 200, 300};
    vec.insert(vec.end(), other.begin(), other.end());
    std::cout << "插入另一个vector后: ";
    for (int n : vec) std::cout << n << " ";  // 1 2 99 3 88 88 88 4 5 100 200 300
    std::cout << std::endl;
    
    // 6. 删除指定位置元素
    vec.erase(vec.begin() + 3);  // 删除第4个元素(索引3)
    std::cout << "删除位置3后: ";
    for (int n : vec) std::cout << n << " ";  // 1 2 99 88 88 88 4 5 100 200 300
    std::cout << std::endl;
    
    // 7. 删除一个范围
    vec.erase(vec.begin() + 3, vec.begin() + 6);  // 删除位置3-5
    std::cout << "删除位置3-5后: ";
    for (int n : vec) std::cout << n << " ";  // 1 2 99 4 5 100 200 300
    std::cout << std::endl;
    
    // 8. 清空所有元素
    vec.clear();
    std::cout << "clear()后大小: " << vec.size() << std::endl;  // 0
    
    // 9. 赋值操作
    vec = {10, 20, 30, 40, 50};
    std::cout << "赋值后: ";
    for (int n : vec) std::cout << n << " ";
    std::cout << std::endl;
    
    // 10. 交换两个vector
    std::vector<int> vec2 = {100, 200, 300};
    std::cout << "\n交换前: vec大小=" << vec.size() 
              << ", vec2大小=" << vec2.size() << std::endl;
    
    vec.swap(vec2);
    std::cout << "交换后: vec大小=" << vec.size() 
              << ", vec2大小=" << vec2.size() << std::endl;
    std::cout << "vec: ";
    for (int n : vec) std::cout << n << " ";  // 100 200 300
    std::cout << "\nvec2: ";
    for (int n : vec2) std::cout << n << " ";  // 10 20 30 40 50
    std::cout << std::endl;
    
    // 11. 使用emplace_back (C++11, 避免临时对象)
    struct Person {
        std::string name;
        int age;
        Person(std::string n, int a) : name(std::move(n)), age(a) {
            std::cout << "构造Person: " << name << std::endl;
        }
        Person(const Person& other) : name(other.name), age(other.age) {
            std::cout << "拷贝Person: " << name << std::endl;
        }
    };
    
    std::vector<Person> people;
    std::cout << "\nemplace_back演示:" << std::endl;
    
    // 传统方法: 创建临时对象再拷贝
    people.push_back(Person("Alice", 25));  // 构造+拷贝
    
    // 现代方法: 直接在vector中构造
    people.emplace_back("Bob", 30);  // 只构造一次
    
    // 12. 使用emplace在指定位置构造
    people.emplace(people.begin(), "Charlie", 35);
}

5. 迭代器和算法

复制代码
复制代码
复制代码
#include <algorithm>
#include <numeric>

void vector_algorithms() {
    std::vector<int> vec = {5, 2, 8, 1, 9, 3, 7, 4, 6};
    
    // 1. 使用STL算法排序
    std::sort(vec.begin(), vec.end());
    std::cout << "排序后: ";
    for (int n : vec) std::cout << n << " ";
    std::cout << std::endl;
    
    // 2. 反转
    std::reverse(vec.begin(), vec.end());
    std::cout << "反转后: ";
    for (int n : vec) std::cout << n << " ";
    std::cout << std::endl;
    
    // 3. 查找
    auto it = std::find(vec.begin(), vec.end(), 7);
    if (it != vec.end()) {
        std::cout << "找到7,位置: " << std::distance(vec.begin(), it) << std::endl;
    }
    
    // 4. 二分查找 (需要先排序)
    std::sort(vec.begin(), vec.end());
    bool found = std::binary_search(vec.begin(), vec.end(), 5);
    std::cout << "二分查找5: " << (found ? "找到" : "未找到") << std::endl;
    
    // 5. 统计
    int count = std::count(vec.begin(), vec.end(), 3);
    std::cout << "数字3出现次数: " << count << std::endl;
    
    // 6. 累加
    int sum = std::accumulate(vec.begin(), vec.end(), 0);
    std::cout << "总和: " << sum << std::endl;
    
    // 7. 变换
    std::vector<int> squared;
    std::transform(vec.begin(), vec.end(), std::back_inserter(squared),
                  [](int x) { return x * x; });
    
    std::cout << "平方: ";
    for (int n : squared) std::cout << n << " ";
    std::cout << std::endl;
    
    // 8. 删除重复元素
    std::vector<int> with_duplicates = {1, 2, 2, 3, 3, 3, 4, 5};
    std::sort(with_duplicates.begin(), with_duplicates.end());
    auto last = std::unique(with_duplicates.begin(), with_duplicates.end());
    with_duplicates.erase(last, with_duplicates.end());
    
    std::cout << "去重后: ";
    for (int n : with_duplicates) std::cout << n << " ";
    std::cout << std::endl;
    
    // 9. 删除满足条件的元素
    std::vector<int> numbers = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
    numbers.erase(std::remove_if(numbers.begin(), numbers.end(),
                               [](int x) { return x % 2 == 0; }),  // 删除偶数
                  numbers.end());
    
    std::cout << "删除偶数后: ";
    for (int n : numbers) std::cout << n << " ";
    std::cout << std::endl;
}

性能特性

时间复杂度

操作 时间复杂度 说明
随机访问 O(1) 通过索引直接访问
尾部插入/删除 平摊O(1) push_back/pop_back
中间/头部插入/删除 O(n) 需要移动元素
查找 O(n) 线性查找
排序 O(n log n) std::sort
扩容 O(n) 需要复制所有元素到新内存

内存管理

复制代码
复制代码
复制代码
void vector_memory_demo() {
    std::cout << "vector内存管理演示:" << std::endl;
    std::vector<int> vec;
    
    std::cout << "初始状态:" << std::endl;
    std::cout << "大小: " << vec.size() 
              << ", 容量: " << vec.capacity() << std::endl;
    
    // 添加元素,观察容量增长
    for (int i = 0; i < 20; ++i) {
        vec.push_back(i);
        std::cout << "添加" << i << "后: 大小=" << vec.size() 
                  << ", 容量=" << vec.capacity() << std::endl;
    }
    
    // 注意:不同编译器的扩容策略可能不同
    // 常见策略是容量翻倍或按固定系数增长
}

高级用法

1. 二维vector

复制代码
复制代码
复制代码
void two_dimensional_vector() {
    // 创建二维vector
    std::vector<std::vector<int>> matrix;
    
    // 方法1: 逐行添加
    matrix.push_back({1, 2, 3});
    matrix.push_back({4, 5, 6});
    matrix.push_back({7, 8, 9});
    
    std::cout << "矩阵1:" << std::endl;
    for (const auto& row : matrix) {
        for (int val : row) {
            std::cout << val << " ";
        }
        std::cout << std::endl;
    }
    
    // 方法2: 指定大小
    int rows = 3, cols = 4;
    std::vector<std::vector<int>> matrix2(rows, std::vector<int>(cols, 0));
    
    // 初始化值
    int count = 1;
    for (int i = 0; i < rows; ++i) {
        for (int j = 0; j < cols; ++j) {
            matrix2[i][j] = count++;
        }
    }
    
    std::cout << "\n矩阵2:" << std::endl;
    for (int i = 0; i < rows; ++i) {
        for (int j = 0; j < cols; ++j) {
            std::cout << matrix2[i][j] << "\t";
        }
        std::cout << std::endl;
    }
    
    // 访问元素
    std::cout << "\nmatrix2[1][2] = " << matrix2[1][2] << std::endl;
    
    // 获取行数和列数
    std::cout << "行数: " << matrix2.size() << std::endl;
    if (!matrix2.empty()) {
        std::cout << "列数: " << matrix2[0].size() << std::endl;
    }
}

2. vector存储自定义对象

复制代码
复制代码
复制代码
class Student {
private:
    std::string name;
    int score;
    
public:
    Student() : name(""), score(0) {}
    Student(std::string n, int s) : name(std::move(n)), score(s) {}
    
    // 用于排序的比较函数
    bool operator<(const Student& other) const {
        return score > other.score;  // 按分数降序
    }
    
    // 用于find_if的匹配函数
    bool hasName(const std::string& searchName) const {
        return name == searchName;
    }
    
    void display() const {
        std::cout << name << ": " << score << "分" << std::endl;
    }
    
    int getScore() const { return score; }
};

void custom_object_vector() {
    std::vector<Student> students;
    
    // 添加学生
    students.emplace_back("Alice", 85);
    students.emplace_back("Bob", 92);
    students.emplace_back("Charlie", 78);
    students.emplace_back("David", 88);
    students.emplace_back("Eve", 95);
    
    std::cout << "学生列表:" << std::endl;
    for (const auto& student : students) {
        student.display();
    }
    
    // 按分数排序
    std::sort(students.begin(), students.end());
    
    std::cout << "\n按分数排序后:" << std::endl;
    for (const auto& student : students) {
        student.display();
    }
    
    // 查找特定学生
    std::string searchName = "Charlie";
    auto it = std::find_if(students.begin(), students.end(),
                          [&searchName](const Student& s) {
                              return s.hasName(searchName);
                          });
    
    if (it != students.end()) {
        std::cout << "\n找到" << searchName << ": ";
        it->display();
    }
    
    // 计算平均分
    int total = std::accumulate(students.begin(), students.end(), 0,
                               [](int sum, const Student& s) {
                                   return sum + s.getScore();
                               });
    double average = static_cast<double>(total) / students.size();
    std::cout << "\n平均分: " << average << std::endl;
    
    // 使用lambda表达式过滤
    std::cout << "\n90分以上的学生:" << std::endl;
    std::for_each(students.begin(), students.end(),
                 [](const Student& s) {
                     if (s.getScore() >= 90) {
                         s.display();
                     }
                 });
}

3. vector的性能优化技巧

复制代码
复制代码
复制代码
void vector_performance_tips() {
    std::cout << "vector性能优化技巧:" << std::endl;
    
    // 技巧1: 预先分配足够容量
    {
        std::cout << "\n1. 预先分配容量:" << std::endl;
        const int N = 1000000;
        
        // 方法1: 不预分配 (多次重新分配)
        std::vector<int> vec1;
        auto start = std::chrono::high_resolution_clock::now();
        for (int i = 0; i < N; ++i) {
            vec1.push_back(i);
        }
        auto end = std::chrono::high_resolution_clock::now();
        auto duration1 = std::chrono::duration_cast<std::chrono::milliseconds>(end - start);
        std::cout << "不预分配耗时: " << duration1.count() << "ms" << std::endl;
        
        // 方法2: 预分配容量
        std::vector<int> vec2;
        vec2.reserve(N);  // 关键步骤
        start = std::chrono::high_resolution_clock::now();
        for (int i = 0; i < N; ++i) {
            vec2.push_back(i);
        }
        end = std::chrono::high_resolution_clock::now();
        auto duration2 = std::chrono::duration_cast<std::chrono::milliseconds>(end - start);
        std::cout << "预分配耗时: " << duration2.count() << "ms" << std::endl;
        std::cout << "性能提升: " << (duration1.count() - duration2.count()) << "ms" << std::endl;
    }
    
    // 技巧2: 使用emplace_back避免拷贝
    {
        std::cout << "\n2. emplace_back vs push_back:" << std::endl;
        struct Point {
            int x, y, z;
            Point(int a, int b, int c) : x(a), y(b), z(c) {
                // std::cout << "构造Point" << std::endl;
            }
            Point(const Point& other) : x(other.x), y(other.y), z(other.z) {
                // std::cout << "拷贝Point" << std::endl;
            }
        };
        
        std::vector<Point> points1;
        std::cout << "使用push_back(会创建临时对象):" << std::endl;
        points1.push_back(Point(1, 2, 3));  // 构造临时对象 + 拷贝
        
        std::vector<Point> points2;
        std::cout << "使用emplace_back(直接构造):" << std::endl;
        points2.emplace_back(1, 2, 3);  // 只构造一次
    }
    
    // 技巧3: 避免在vector中存储大对象
    {
        std::cout << "\n3. 存储指针而不是大对象:" << std::endl;
        struct LargeObject {
            int data[1000];  // 大对象
        };
        
        // 存储对象本身 (可能效率低)
        std::vector<LargeObject> objects;
        
        // 存储智能指针 (更高效)
        std::vector<std::shared_ptr<LargeObject>> object_ptrs;
        object_ptrs.push_back(std::make_shared<LargeObject>());
    }
    
    // 技巧4: 正确使用swap
    {
        std::cout << "\n4. 使用swap快速清空vector:" << std::endl;
        std::vector<int> vec(1000000, 42);
        std::cout << "清空前: 大小=" << vec.size() 
                  << ", 容量=" << vec.capacity() << std::endl;
        
        // 方法1: clear() 不释放内存
        vec.clear();
        std::cout << "clear()后: 大小=" << vec.size() 
                  << ", 容量=" << vec.capacity() << std::endl;
        
        // 方法2: swap技巧释放内存
        std::vector<int>().swap(vec);
        std::cout << "swap后: 大小=" << vec.size() 
                  << ", 容量=" << vec.capacity() << std::endl;
    }
}

常见错误和注意事项

复制代码
复制代码
复制代码
void common_mistakes() {
    std::cout << "常见错误和注意事项:" << std::endl;
    
    // 错误1: 迭代器失效
    {
        std::cout << "\n1. 迭代器失效问题:" << std::endl;
        std::vector<int> vec = {1, 2, 3, 4, 5};
        auto it = vec.begin() + 2;  // 指向3
        
        // 在插入/删除后,迭代器可能失效
        vec.push_back(6);  // 可能导致重新分配内存
        // it 可能已经失效!
        
        // 安全做法:重新获取迭代器
        it = vec.begin() + 2;
        std::cout << "安全访问: " << *it << std::endl;
    }
    
    // 错误2: 越界访问
    {
        std::cout << "\n2. 越界访问:" << std::endl;
        std::vector<int> vec = {1, 2, 3};
        
        // 危险:不检查边界
        // int val = vec[10];  // 未定义行为
        
        // 安全:使用at(),会抛出异常
        try {
            int val = vec.at(10);  // 抛出std::out_of_range
        } catch (const std::out_of_range& e) {
            std::cout << "捕获异常: " << e.what() << std::endl;
        }
    }
    
    // 错误3: 引用失效
    {
        std::cout << "\n3. 引用失效问题:" << std::endl;
        std::vector<int> vec = {1, 2, 3};
        int& ref = vec[1];  // 引用第二个元素
        
        vec.push_back(4);  // 可能导致重新分配
        // ref 现在可能无效!
        
        // 安全做法:避免在修改操作后使用引用
        std::cout << "安全做法: 立即使用引用" << std::endl;
    }
    
    // 错误4: 错误使用reserve
    {
        std::cout << "\n4. reserve不改变大小:" << std::endl;
        std::vector<int> vec;
        vec.reserve(10);  // 只分配内存,不创建元素
        
        // vec[0] = 1;  // 错误!size()还是0
        
        // 正确做法
        vec.push_back(1);  // 或者使用resize
        std::cout << "正确: vec[0] = " << vec[0] << std::endl;
    }
}

综合示例:学生成绩管理系统

复制代码
复制代码
复制代码
#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
#include <numeric>
#include <iomanip>

class StudentGradeSystem {
private:
    struct Student {
        int id;
        std::string name;
        double grade;
        
        Student(int i, std::string n, double g) 
            : id(i), name(std::move(n)), grade(g) {}
        
        void display() const {
            std::cout << std::setw(5) << id 
                      << std::setw(15) << name 
                      << std::setw(8) << std::fixed << std::setprecision(2) << grade << std::endl;
        }
    };
    
    std::vector<Student> students;
    
public:
    // 添加学生
    void addStudent(int id, const std::string& name, double grade) {
        students.emplace_back(id, name, grade);
        std::cout << "添加学生: " << name << " (ID: " << id << ")" << std::endl;
    }
    
    // 显示所有学生
    void displayAll() const {
        if (students.empty()) {
            std::cout << "没有学生记录。" << std::endl;
            return;
        }
        
        std::cout << "\n学生成绩列表:" << std::endl;
        std::cout << std::setw(5) << "ID" 
                  << std::setw(15) << "姓名" 
                  << std::setw(8) << "成绩" << std::endl;
        std::cout << std::string(30, '-') << std::endl;
        
        for (const auto& student : students) {
            student.display();
        }
    }
    
    // 按成绩排序
    void sortByGrade(bool descending = true) {
        std::sort(students.begin(), students.end(),
                 [descending](const Student& a, const Student& b) {
                     return descending ? a.grade > b.grade : a.grade < b.grade;
                 });
        std::cout << "已按成绩" << (descending ? "降序" : "升序") << "排序。" << std::endl;
    }
    
    // 查找学生
    void findStudent(int id) const {
        auto it = std::find_if(students.begin(), students.end(),
                              [id](const Student& s) { return s.id == id; });
        
        if (it != students.end()) {
            std::cout << "找到学生:" << std::endl;
            it->display();
        } else {
            std::cout << "未找到ID为" << id << "的学生。" << std::endl;
        }
    }
    
    // 查找学生(按姓名)
    void findStudent(const std::string& name) const {
        auto it = std::find_if(students.begin(), students.end(),
                              [&name](const Student& s) { return s.name == name; });
        
        if (it != students.end()) {
            std::cout << "找到学生:" << std::endl;
            it->display();
        } else {
            std::cout << "未找到姓名为" << name << "的学生。" << std::endl;
        }
    }
    
    // 删除学生
    void removeStudent(int id) {
        auto it = std::remove_if(students.begin(), students.end(),
                                [id](const Student& s) { return s.id == id; });
        
        if (it != students.end()) {
            students.erase(it, students.end());
            std::cout << "已删除ID为" << id << "的学生。" << std::endl;
        } else {
            std::cout << "未找到ID为" << id << "的学生。" << std::endl;
        }
    }
    
    // 统计信息
    void showStatistics() const {
        if (students.empty()) {
            std::cout << "没有学生数据可统计。" << std::endl;
            return;
        }
        
        // 计算平均分
        double total = std::accumulate(students.begin(), students.end(), 0.0,
                                      [](double sum, const Student& s) { return sum + s.grade; });
        double average = total / students.size();
        
        // 找到最高分和最低分
        auto minmax = std::minmax_element(students.begin(), students.end(),
                                         [](const Student& a, const Student& b) {
                                             return a.grade < b.grade;
                                         });
        
        std::cout << "\n成绩统计:" << std::endl;
        std::cout << "学生总数: " << students.size() << std::endl;
        std::cout << "平均成绩: " << std::fixed << std::setprecision(2) << average << std::endl;
        std::cout << "最高分: " << minmax.second->name << " - " << minmax.second->grade << std::endl;
        std::cout << "最低分: " << minmax.first->name << " - " << minmax.first->grade << std::endl;
    }
    
    // 筛选优秀学生
    void showTopStudents(double threshold = 90.0) const {
        std::vector<Student> topStudents;
        std::copy_if(students.begin(), students.end(), std::back_inserter(topStudents),
                    [threshold](const Student& s) { return s.grade >= threshold; });
        
        if (topStudents.empty()) {
            std::cout << "没有学生达到" << threshold << "分以上。" << std::endl;
            return;
        }
        
        std::cout << "\n优秀学生 (" << threshold << "分以上):" << std::endl;
        for (const auto& student : topStudents) {
            student.display();
        }
    }
};

void student_system_demo() {
    StudentGradeSystem system;
    
    // 添加学生
    system.addStudent(1001, "张三", 85.5);
    system.addStudent(1002, "李四", 92.0);
    system.addStudent(1003, "王五", 78.5);
    system.addStudent(1004, "赵六", 88.0);
    system.addStudent(1005, "钱七", 95.5);
    system.addStudent(1006, "孙八", 91.0);
    
    // 显示所有学生
    system.displayAll();
    
    // 按成绩排序
    system.sortByGrade();
    system.displayAll();
    
    // 查找学生
    system.findStudent(1003);
    system.findStudent("李四");
    
    // 统计信息
    system.showStatistics();
    
    // 显示优秀学生
    system.showTopStudents(90.0);
    
    // 删除学生
    system.removeStudent(1003);
    system.displayAll();
    
    // 再次统计
    system.showStatistics();
}

int main() {
    std::cout << "===== C++ vector 容器详细文档 =====\n" << std::endl;
    
    std::cout << "=== 1. 创建和初始化 ===" << std::endl;
    create_vector();
    
    std::cout << "\n=== 2. 元素访问 ===" << std::endl;
    vector_access();
    
    std::cout << "\n=== 3. 容量和大小 ===" << std::endl;
    vector_capacity();
    
    std::cout << "\n=== 4. 元素修改 ===" << std::endl;
    vector_modification();
    
    std::cout << "\n=== 5. 算法应用 ===" << std::endl;
    vector_algorithms();
    
    std::cout << "\n=== 6. 二维vector ===" << std::endl;
    two_dimensional_vector();
    
    std::cout << "\n=== 7. 自定义对象vector ===" << std::endl;
    custom_object_vector();
    
    std::cout << "\n=== 8. 性能优化 ===" << std::endl;
    vector_performance_tips();
    
    std::cout << "\n=== 9. 常见错误 ===" << std::endl;
    common_mistakes();
    
    std::cout << "\n=== 10. 综合示例: 学生成绩管理系统 ===" << std::endl;
    student_system_demo();
    
    return 0;
}

总结

vector的主要优点:

  1. 动态大小:自动管理内存,根据需要增长

  2. 随机访问:通过索引快速访问元素,时间复杂度O(1)

  3. 连续存储:内存局部性好,缓存友好

  4. 丰富的接口:提供多种操作和算法支持

  5. 类型安全:编译时类型检查

适用场景:

  • 需要频繁随机访问元素

  • 主要在尾部添加/删除元素

  • 元素数量不确定或经常变化

  • 需要与其他STL算法配合使用

不适用场景:

  • 频繁在头部或中间插入/删除元素(考虑使用list或deque)

  • 元素非常大且频繁重新分配(考虑存储指针)

  • 需要固定大小数组(考虑使用array)

最佳实践:

  1. 使用reserve()预分配空间以提高性能

  2. 使用emplace_back()替代push_back()避免拷贝

  3. 注意迭代器和引用失效问题

  4. 使用at()进行安全的边界检查访问

  5. 使用范围for循环简化遍历

  6. 结合STL算法提高代码可读性和效率

相关推荐
艾莉丝努力练剑2 小时前
【Linux线程】Linux系统多线程(八):<策略模式>日志系统的封装实现
linux·运维·服务器·c++·学习·策略模式
盐焗鹌鹑蛋2 小时前
【C++】string模拟实现
c++
特种加菲猫2 小时前
C++进阶:模板深度解析与继承机制初探
开发语言·c++
旖-旎2 小时前
递归(快速幂)(5)
c++·算法·力扣·递归
大江东去浪淘尽千古风流人物5 小时前
【cuVSLAM】GPU 加速、多相机、实时视觉/视觉惯性 SLAM设计优势
c++·人工智能·数码相机·ubuntu·计算机视觉·augmented reality
自信1504130575911 小时前
重生之从0开始学习c++之模板初级
c++·学习
历程里程碑11 小时前
2. Git版本回退全攻略:轻松掌握代码时光机
大数据·c++·git·elasticsearch·搜索引擎·github·全文检索
极客智造12 小时前
深度解析 C++ 类继承与多态:面向对象编程的核心
c++
零号全栈寒江独钓14 小时前
基于c/c++实现linux/windows跨平台获取ntp网络时间戳
linux·c语言·c++·windows