第一章:std::vector 核心函数列表与详解

1. 构造与赋值函数

构造函数

  • 函数功能:支持默认构造、填充构造(大小+初始值)、范围构造(迭代器)、拷贝构造、移动构造及初始化列表构造。
  • 函数入参:依构造方式不同,可传入 size_type count, const T& value, InputIt first/last, const vector& other, vector&& other, initializer_list<T> 等。
  • 函数返回值:无(构造对象本身)
  • 使用举例
    std::vector<int> v1;                      // 默认构造(空)
    std::vector<int> v2(5);                   // 填充构造(5个默认值)
    std::vector<int> v3(5, 42);               // 填充构造(5个42)
    std::vector<int> v4(v3);                  // 拷贝构造
    std::vector<int> v5(std::move(v4));       // 移动构造
    int arr[] = {1, 2, 3};
    std::vector<int> v6(arr, arr + 3);        // 迭代器范围构造
    std::vector<int> v7 = {10, 20, 30};       // 初始化列表构造
    

operator=

  • 函数功能:替换容器内容。支持拷贝赋值、移动赋值和初始化列表赋值。
  • 函数入参const vector& other / vector&& other / initializer_list<T>
  • 函数返回值vector& (指向自身的引用)
  • 使用举例
    std::vector<int> src = {1, 2, 3};
    std::vector<int> dst;
    dst = src;                                  // 拷贝赋值
    dst = std::move(src);                       // 移动赋值
    dst = {10, 20, 30};                         // 初始化列表赋值
    

assign

  • 函数功能:替换容器内容。支持填充赋值、迭代器范围赋值和初始化列表赋值。
  • 函数入参size_type count, const T& valueInputIt first, lastinitializer_list<T>
  • 函数返回值:无 (void)
  • 使用举例
    std::vector<int> v;
    v.assign(4, 99);                            // 4个99: [99,99,99,99]
    int arr[] = {1, 2, 3};
    v.assign(arr, arr + 3);                     // 从数组范围: [1,2,3]
    v.assign({10, 20, 30});                     // 初始化列表: [10,20,30]
    

2. 元素访问函数

operator[]

  • 函数功能:访问指定位置的元素,不进行边界检查,性能最高。
  • 函数入参size_type pos (元素索引)
  • 函数返回值referenceconst_reference
  • 使用举例
    std::vector<int> v = {10, 20, 30};
    int x = v[0];                               // 读取首元素:10
    v[1] = 99;                                  // 修改元素:[10,99,30]
    

at

  • 函数功能:访问指定位置的元素,进行边界检查,越界时抛出 std::out_of_range 异常。
  • 函数入参size_type pos (元素索引)
  • 函数返回值referenceconst_reference
  • 使用举例
    std::vector<int> v = {10, 20, 30};
    try {
        int x = v.at(2);                        // 正常访问:30
        v.at(100) = 0;                          // 越界,抛出异常
    } catch (const std::out_of_range& e) {
        // 处理越界
    }
    

front

  • 函数功能:访问容器的第一个元素。
  • 函数入参:无
  • 函数返回值referenceconst_reference
  • 使用举例
    std::vector<int> v = {10, 20, 30};
    int first = v.front();                      // 获取首元素:10
    v.front() = 100;                            // 修改首元素:[100,20,30]
    

back

  • 函数功能:访问容器的最后一个元素。
  • 函数入参:无
  • 函数返回值referenceconst_reference
  • 使用举例
    std::vector<int> v = {10, 20, 30};
    int last = v.back();                        // 获取尾元素:30
    v.back() = 300;                             // 修改尾元素:[10,20,300]
    

data

  • 函数功能:返回指向底层连续内存数组的指针,常用于与 C 风格 API 交互。
  • 函数入参:无
  • 函数返回值T*const T*
  • 使用举例
    std::vector<int> v = {10, 20, 30};
    int* p = v.data();                          // 获取裸指针
    int second = *(p + 1);                      // 通过指针访问:20
    // 可传入需要 C 风格数组的函数,如:memcpy(arr, v.data(), v.size()*sizeof(int))
    

3. 迭代器函数

begin / end

  • 函数功能:返回指向首元素 / 尾后元素的普通迭代器。
  • 函数入参:无
  • 函数返回值iteratorconst_iterator
  • 使用举例
    std::vector<int> v = {1, 2, 3};
    for (auto it = v.begin(); it != v.end(); ++it) {
        std::cout << *it << " ";                // 输出:1 2 3
    }
    

cbegin / cend

  • 函数功能:返回指向首元素 / 尾后元素的常量迭代器 (C++11)。
  • 函数入参:无
  • 函数返回值const_iterator
  • 使用举例
    const std::vector<int> v = {1, 2, 3};
    for (auto it = v.cbegin(); it != v.cend(); ++it) {
        std::cout << *it << " ";                // 只读遍历
    }
    

rbegin / rend

  • 函数功能:返回指向首元素 / 尾后元素的反向迭代器。
  • 函数入参:无
  • 函数返回值reverse_iteratorconst_reverse_iterator
  • 使用举例
    std::vector<int> v = {1, 2, 3};
    for (auto it = v.rbegin(); it != v.rend(); ++it) {
        std::cout << *it << " ";                // 逆序输出:3 2 1
    }
    

crbegin / crend

  • 函数功能:返回指向首元素 / 尾后元素的常量反向迭代器 (C++11)。
  • 函数入参:无
  • 函数返回值const_reverse_iterator
  • 使用举例
    const std::vector<int> v = {1, 2, 3};
    for (auto it = v.crbegin(); it != v.crend(); ++it) {
        std::cout << *it << " ";                // 只读逆序:3 2 1
    }
    

4. 容量管理函数

empty

  • 函数功能:检查容器是否为空。
  • 函数入参:无
  • 函数返回值bool
  • 使用举例
    std::vector<int> v;
    if (v.empty()) {                            // true
        // 容器为空时的处理
    }
    

size

  • 函数功能:返回容器中当前元素的个数。
  • 函数入参:无
  • 函数返回值size_type
  • 使用举例
    std::vector<int> v = {1, 2, 3, 4};
    std::size_t n = v.size();                   // n = 4
    

max_size

  • 函数功能:返回容器支持的最大元素数量(理论极限)。
  • 函数入参:无
  • 函数返回值size_type
  • 使用举例
    std::vector<int> v;
    std::size_t max = v.max_size();             // 理论最大元素数
    

capacity

  • 函数功能:返回当前已分配的底层内存空间可容纳的元素数量。
  • 函数入参:无
  • 函数返回值size_type
  • 使用举例
    std::vector<int> v;
    v.reserve(100);
    std::size_t cap = v.capacity();             // cap >= 100
    

reserve

  • 函数功能:预分配内存,增加 capacity不改变 size,避免频繁扩容。
  • 函数入参size_type new_cap (新的容量需求)
  • 函数返回值:无 (void)
  • 使用举例
    std::vector<int> v;
    v.reserve(1000);                            // 预先分配1000个元素的空间
    for (int i = 0; i < 1000; ++i) {
        v.push_back(i);                         // 不再触发多次扩容
    }
    

resize

  • 函数功能:改变容器中元素的个数 (size)。若增加则值初始化或填充,若减少则截断。
  • 函数入参size_type count, 可选 const T& value (填充值)
  • 函数返回值:无 (void)
  • 使用举例
    std::vector<int> v = {1, 2, 3};
    v.resize(5);                                // 变大:[1,2,3,0,0]
    v.resize(10, 99);                           // 变大:[1,2,3,0,0,99,99,99,99,99]
    v.resize(2);                                // 变小:[1,2]
    

shrink_to_fit

  • 函数功能:请求移除未使用的容量,使 capacity 尽量贴近 size (C++11,请求性操作)。
  • 函数入参:无
  • 函数返回值:无 (void)
  • 使用举例
    std::vector<int> v;
    v.reserve(100);
    v.push_back(1);
    v.shrink_to_fit();                          // 请求释放多余容量
    

5. 修改操作函数

clear

  • 函数功能:清空所有元素,size 变为 0,但 capacity 保持不变。
  • 函数入参:无
  • 函数返回值:无 (void)
  • 使用举例
    std::vector<int> v = {1, 2, 3};
    v.clear();                                  // 清空元素,size=0, capacity不变
    

insert

  • 函数功能:在指定迭代器位置前插入元素。支持单个、多个相同元素、迭代器范围及初始化列表。
  • 函数入参iterator pos, 以及 const T& value / count / first, last / initializer_list
  • 函数返回值:指向首个插入元素的 iterator
  • 使用举例
    std::vector<int> v = {1, 2, 3};
    v.insert(v.begin(), 0);                     // 首前插入:[0,1,2,3]
    v.insert(v.end(), 3, 9);                    // 末尾插入3个9
    int arr[] = {10, 20};
    v.insert(v.begin(), arr, arr + 2);          // 插入范围
    v.insert(v.begin(), {100, 200});            // 初始化列表插入
    

emplace

  • 函数功能:在指定位置原位构造元素,避免临时对象的拷贝/移动开销 (C++11)。
  • 函数入参iterator pos, Args&&... args (构造参数)
  • 函数返回值:指向新构造元素的 iterator
  • 使用举例
    std::vector<std::pair<int,int>> v;
    v.emplace(v.begin(), 1, 2);                 // 原位构造 pair(1,2)
    

erase

  • 函数功能:移除指定位置或范围内的元素,导致被删位置及之后的迭代器失效。
  • 函数入参iterator positerator first, last
  • 函数返回值:指向被删元素后一个元素的 iterator
  • 使用举例
    std::vector<int> v = {1, 2, 3, 4, 5};
    v.erase(v.begin());                         // 删除首元素:[2,3,4,5]
    v.erase(v.begin(), v.begin() + 2);          // 删除范围:[4,5]
    

push_back

  • 函数功能:在容器尾部添加元素(拷贝或移动)。
  • 函数入参const T& valueT&& value
  • 函数返回值:无 (void)
  • 使用举例
    std::vector<int> v;
    v.push_back(1);                             // 尾部加1
    v.push_back(2);                             // 尾部加2 → [1,2]
    

emplace_back

  • 函数功能:在容器尾部原位构造元素,避免临时对象开销 (C++11)。
  • 函数入参Args&&... args (构造参数)
  • 函数返回值reference (C++17起返回引用)
  • 使用举例
    std::vector<std::string> v;
    v.emplace_back("hello");                    // 原位构造 string
    v.emplace_back(5, 'a');                     // 原位构造 "aaaaa"
    

pop_back

  • 函数功能:移除容器的最后一个元素。
  • 函数入参:无
  • 函数返回值:无 (void)
  • 使用举例
    std::vector<int> v = {1, 2, 3};
    v.pop_back();                               // 移除末尾 → [1,2]
    

swap

  • 函数功能:交换两个容器的内容,时间复杂度 O(1),仅交换内部指针。
  • 函数入参vector& other
  • 函数返回值:无 (void)
  • 使用举例
    std::vector<int> a = {1, 2}, b = {3, 4};
    a.swap(b);                                  // a=[3,4], b=[1,2]
    

6. 非成员函数与特有函数

比较运算符

  • 函数功能:按字典序逐元素比较两个 vector (==, !=, <, <=, >, >=)。
  • 函数入参const vector& lhs, const vector& rhs
  • 函数返回值bool
  • 使用举例
    std::vector<int> a = {1, 2, 3};
    std::vector<int> b = {1, 2, 4};
    bool eq = (a == b);                         // false
    bool lt = (a < b);                          // true(逐元素比较)
    

std::swap

  • 函数功能:非成员版本的交换函数,通过 ADL 机制优先调用成员 swap
  • 函数入参vector& lhs, vector& rhs
  • 函数返回值:无 (void)
  • 使用举例
    std::vector<int> a = {1, 2}, b = {3, 4};
    std::swap(a, b);                            // 调用 ADL 的 swap
    

flip

  • 函数功能vector<bool> 特有:将所有位(元素)取反。
  • 函数入参:无
  • 函数返回值:无 (void)
  • 使用举例
    std::vector<bool> vb = {true, false, true};
    vb.flip();                                  // 变为 [false, true, false]
    

第二章:分模块代码示例

2.1 构造函数与赋值

包含默认构造、带参构造、拷贝/移动构造、迭代器范围构造、初始化列表构造,以及 assign 赋值和基于 new / 智能指针的堆内存动态创建。

void demo_constructors()
{
    std::cout << "\n====== 1. 构造函数与赋值 ======\n";
    std::vector<int> v1; // 默认构造
    std::vector<int> v2(5); // 填充构造
    std::vector<int> v3(5, 42); // 填充构造带初始值
    std::vector<int> v4(v3); // 拷贝构造
    std::vector<int> v5(std::move(v4)); // 移动构造
    int arr[] = { 10, 20, 30 };
    std::vector<int> v6(std::begin(arr), std::end(arr)); // 迭代器范围构造
    std::vector<int> v7 = { 1, 2, 3 }; // 初始化列表构造

    v1 = v7; // 拷贝赋值
    v2 = std::move(v1); // 移动赋值
    v3 = { 100, 200 }; // 初始化列表赋值
    v4.assign(4, 999); // assign 批量赋值

    // new 动态创建与智能指针管理
    auto upv = std::make_unique<std::vector<int>>(std::initializer_list<int>{1, 2, 3});
    upv->push_back(4);
}

2.2 元素访问

演示 operator[](无边界检查)、at()(带边界检查及异常捕获)、front()/back()(首尾访问)以及 data()(获取底层数组指针)。

void demo_element_access()
{
    std::vector<int> vec = { 10, 20, 30, 40, 50 };
    vec[2] = 300; // 下标访问
    try { vec.at(100); } // 越界异常捕获
    catch (const std::out_of_range& e) { /* ... */ }

    vec.front() = 1000; // 修改首元素
    vec.back() = 5000;  // 修改尾元素
    int* p = vec.data(); // 获取底层指针
}

2.3 迭代器

演示正向、反向、常量迭代器的使用,以及 C++11 范围 for 循环的底层逻辑。

void demo_iterators()
{
    std::vector<int> vec = { 1, 2, 3, 4, 5 };
    for (auto it = vec.begin(); it != vec.end(); it++) { /* 正向迭代 */ }
    for (auto it = vec.cbegin(); it != vec.cend(); it++) { /* const 迭代 */ }
    for (auto it = vec.rbegin(); it != vec.rend(); it++) { /* 反向迭代 */ }
    for (int x : vec) { /* 范围 for 循环 */ }
}

2.4 容量操作

演示 emptysizecapacitymax_size 的查询,以及 reserve(预分配内存)、resize(改变元素个数)和 shrink_to_fit(释放多余容量)的使用。

void demo_capacity()
{
    std::vector<int> vec;
    vec.reserve(20); // 预分配内存,只改 capacity
    for (int i = 0; i < 10; i++) vec.push_back(i);

    vec.resize(15); // 改变元素个数,新增元素值初始化
    vec.resize(20, 99); // 新增元素用 99 填充
    vec.resize(5);  // 截断尾部元素
    vec.shrink_to_fit(); // 请求释放多余容量
}

2.5 修改操作

演示尾部插入/删除 (push_back, emplace_back, pop_back),指定位置插入/原位构造/删除 (insert, emplace, erase),以及 clearswap(包含利用 swap 释放内存的经典技巧)。

void demo_modifiers()
{
    std::vector<int> vec;
    vec.push_back(1);
    vec.pop_back();

    auto it = vec.begin();
    vec.insert(it, 100); // 指定位置插入
    vec.erase(vec.begin() + 1); // 指定位置删除

    vec.clear(); // 清空元素,capacity 不变

    std::vector<int> huge(10000);
    huge.clear();
    std::vector<int>().swap(huge); // 利用 swap 强制释放内存
}

2.6 与 STL 算法配合

演示 vector<algorithm><numeric> 库中算法的结合,包括排序、查找、计数、遍历、变换、累加、去重、二分查找及 C++20 的 std::erase

void demo_algorithms()
{
    std::vector<int> vec = { 5, 2, 8, 1, 9 };
    std::sort(vec.begin(), vec.end()); // 排序
    auto it = std::find(vec.begin(), vec.end(), 7); // 查找
    int sum = std::accumulate(vec.begin(), vec.end(), 0); // 累加

    // 删除-擦除惯用法 (Erase-Remove Idiom)
    vec.erase(std::remove_if(vec.begin(), vec.end(), [](int x) {return x % 2 == 0; }), vec.end());
}

2.7 非成员函数与比较

演示 vector 的字典序比较运算符及非成员 std::swap

void demo_non_member()
{
    std::vector<int> a = { 1, 2, 3 };
    std::vector<int> b = { 1, 2, 4 };
    bool is_less = (a < b); // 字典序比较
    std::swap(a, b); // 非成员 swap
}

2.8 二维 vector

演示二维 vector 的多种创建方式:规则矩阵初始化、初始化列表构造、不规则锯齿数组(逐行 push_back),以及性能最优的 reserve + emplace_back 组合。

void demo_2d_vector()
{
    // M 行 N 列,初始值为 0
    std::vector<std::vector<int>> matrix(3, std::vector<int>(4, 0));

    // 初始化列表
    std::vector<std::vector<int>> mat2 = { {1, 2}, {3, 4} };

    // 锯齿数组
    std::vector<std::vector<int>> jagged;
    jagged.push_back({ 1 });
    jagged.push_back({ 2, 3 });
}

2.9 三维 vector

演示三维 vector(D层 × M行 × N列)的嵌套构造、初始化列表构造及逐层 reserve 构建方式。

void demo_3d_vector()
{
    // D层 × M行 × N列
    std::vector<std::vector<std::vector<int>>> tensor(
        2, std::vector<std::vector<int>>(3, std::vector<int>(4, 0))
    );

    // 初始化列表
    std::vector<std::vector<std::vector<int>>> tensor2 = {
        { {1, 2}, {3, 4} },
        { {5, 6}, {7, 8} }
    };
}

2.10 工程化最佳实践

总结传参规范、reserve 预分配、emplace_back 优化、范围 for 引用修改、迭代器失效的安全循环 erase 写法等工程经验。

void demo_best_practices()
{
    std::vector<int> nums = { 1, 2, 3, 4, 5, 6 };
    // 安全循环 erase
    for (auto it = nums.begin(); it != nums.end(); )
    {
        if (*it % 2 == 0) it = nums.erase(it); // 使用返回值更新迭代器
        else it++;
    }
}

2.11 vector 优化

演示 std::vector<bool> 的特化行为(位压缩存储)及其特有的 flip() 函数,并说明代理引用(Proxy Reference)的潜在陷阱。

void demo_vector_bool()
{
    std::vector<bool> vb = { true, false, true };
    vb.flip(); // 全体取反
}

第三章:完整代码

#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
#include <numeric>
#include <iterator>
#include <stdexcept>
#include <cassert>
#include <initializer_list>
#include <memory>

/*
 * std::vector 全用法工程化示例
 * 涵盖:构造/访问/迭代器/容量/修改/算法/非成员函数/异常安全
 */

 /**
  * @brief
  *      打印 vector 内容(工程化调试工具函数)
  * @tparam T
  * @param vec
  * @param label
  */
template <typename T>
void print_vector(const std::vector<T>& vec, const std::string& label = "")
{
    if (!label.empty())
    {
        std::cout << label << ": ";
    }
    std::cout << "[size=" << vec.size()
        << ", capacity=" << vec.capacity() << "] ";
    for (size_t i = 0; i < vec.size(); ++i)
    {
        if (i > 0) std::cout << ", ";
        std::cout << vec[i];
    }
    std::cout << "\n";
}

/**
 * @brief 自定义类型,用于演示 emplace / 移动语义
 */
class Widget
{
private:
    int m_id;
    std::string m_name;

public:
    // 默认构造
    Widget() : m_id(0) {}

    // 带参构造
    explicit Widget(int id, std::string name = "")
        : m_id(id), m_name(std::move(name))
    {
    }

    // 拷贝构造
    Widget(const Widget& other) = default;

    // 移动构造
    Widget(Widget&& other) noexcept
        : m_id(other.m_id), m_name(std::move(other.m_name))
    {
        other.m_id = 0;
    }

    // 拷贝赋值
    Widget& operator=(const Widget& other) = default;

    // 移动赋值
    Widget& operator=(Widget&& other) noexcept
    {
        if (this != &other)
        {
            m_id = other.m_id;
            m_name = std::move(other.m_name);
            other.m_id = 0;
        }
        return *this;
    }

    int id() const
    {
        return m_id;
    }

    const std::string& name() const
    {
        return m_name;
    }

    bool operator<(const Widget& rhs) const
    {
        return m_id < rhs.m_id;
    }

    bool operator==(const Widget& rhs) const
    {
        return m_id == rhs.m_id;
    }
};

std::ostream& operator<<(std::ostream& os, const Widget& w)
{
    os << "Widget{id=" << w.id() << ", name='" << w.name() << "'}";
    return os;
}

// ============================================================

/**
 * @brief 构造函数与赋值
 */
void demo_constructors()
{
    std::cout << "\n====== 1. 构造函数与赋值 ======\n";

    /* 1.1 默认构造:空 vector */
    std::vector<int> v1;
    print_vector(v1, "默认构造 v1");

    /* 1.2 带初始大小的构造(值初始化,int为0) */
    std::vector<int> v2(5);
    print_vector(v2, "指定大小 v2(5)");

    /* 1.3 指定大小 + 初始值 */
    std::vector<int> v3(5, 42);
    print_vector(v3, "指定大小 v3(5)");

    /* 1.4 拷贝构造 */
    std::vector<int> v4(v3);
    print_vector(v4, "拷贝构造 v4(v3)");

    /* 1.5 移动构造(C++ 11) */
    std::vector<int> v5(std::move(v4));
    print_vector(v5, "移动构造 v5(std::move(v4))");
    print_vector(v4, "移动后 v4 状态");

    /* 1.6 迭代器范围构造 */
    int arr[] = { 10, 20, 30, 40, 50 };
    std::vector<int> v6(std::begin(arr), std::end(arr));
    print_vector(v6, "迭代器范围 v6");

    /* 1.7 初始化列表构造(C++ 11) */
    std::vector<int> v7 = { 1, 2, 3, 4, 5 };
    std::vector<int> v8{ 11, 22, 33 };
    print_vector(v7, "初始化列表 v7");
    print_vector(v8, "初始化列表 v8");

    /* 1.8 拷贝赋值 */
    v1 = v7;
    print_vector(v1, "拷贝赋值 v1 = v7");

    /* 1.9 移动赋值 */
    v2 = std::move(v1);
    print_vector(v2, "移动赋值 v2 = std::move(v1)");

    /* 1.10 initializer_list 赋值 */
    v3 = { 100, 200, 300 };
    print_vector(v3, "初始化列表赋值 v3 = {...}");

    /* 1.11 assign: 批量赋值(大小+值) */
    v4.assign(4, 999);
    print_vector(v4, "assign(4, 999)");

    /* 1.12 assign: 迭代器范围 */
    v5.assign(v8.begin(), v8.end());
    print_vector(v5, "assign(迭代器范围)");

    /* 1.13 assign: 初始化列表 */
    v6.assign({ 7, 8, 9 });
    print_vector(v6, "assign(初始化列表)");

    /* 1.14 new 动态创建 vector (堆分配) */
    {
        std::cout << "\n--- new 动态创建 ---\n";
        // 默认构造
        std::vector<int>* pv1 = new std::vector<int>();
        pv1->push_back(10);
        pv1->push_back(20);
        pv1->push_back(30);
        print_vector(*pv1, "new 默认构造 pv1");

        // 带参构造:指定大小 + 初始值
        std::vector<int>* pv2 = new std::vector<int>(5, 88);
        print_vector(*pv2, "new 指定大小 pv2(5, 88)");

        // 初始化列表构造
        std::vector<int>* pv3 = new std::vector<int>{ 100, 200, 300, 400 };
        print_vector(*pv3, "new 初始化列表 pv3");

        // 拷贝构造(从已有 vector 拷贝)
        std::vector<int>* pv4 = new std::vector<int>(*pv3);
        print_vector(*pv4, "new 拷贝构造 pv4(*pv3)");

        // 使用完毕后必须 delete 释放内存
        delete pv1;
        delete pv2;
        delete pv3;
        delete pv4;

        /*
         * 裸 new 需要手动 delete,极易泄漏,不推荐
         * 优先使用智能指针 std::unique_ptr / std::shared_ptr 管理堆上 vector
         */
        std::cout << "\n--- 智能指针管理堆 vector ---\n";

        // std::unique_ptr 管理(自动释放,零开销)
        auto upv = std::make_unique<std::vector<int>>(std::initializer_list<int>{1, 2, 3});
        upv->push_back(4);
        print_vector(*upv, "unique_ptr vector");

        // std::shared_ptr 管理(引用计数,可共享)
        auto spv = std::make_shared<std::vector<int>>(4, 77);
        print_vector(*spv, "shared_ptr vector");

        // 离开作用域自动释放,无需手动 delete
    }
}

// ============================================================

/**
 * @brief 元素访问
 */
void demo_element_access()
{
    std::cout << "\n====== 2. 元素访问 ======\n";

    std::vector<int> vec = { 10, 20, 30, 40, 50 };
    print_vector(vec, "原始 vec");

    /* 2.1 operator[]: 下标访问,不做边界检查 */
    std::cout << "vec[2] = " << vec[2] << "\n";
    vec[2] = 300;
    std::cout << "修改后 vec[2] = " << vec[2] << "\n";

    /* 2.2 at(): 带边界检查,越界抛出 std::out_of_range */
    try
    {
        std::cout << "vec.at(3) = " << vec.at(3) << "\n";
        std::cout << "vec.at(100) = 越界访问\n";
        vec.at(100);    // 触发异常
    }
    catch (const std::out_of_range& e)
    {
        // invalid vector subscript
        std::cout << "捕获越界异常: " << e.what() << "\n";
    }

    /* 2.3 front() / back(): 首尾元素引用 */
    std::cout << "front() = " << vec.front() << "\n";
    std::cout << "back() = " << vec.back() << "\n";
    vec.front() = 1000;
    vec.back() = 5000;
    print_vector(vec, "修改首尾后");

    /* 2.4 data(): 返回底层数组指针(C++ 11) */
    int* p = vec.data();
    std::cout << "data()[0] = " << p[0] << "\n";
    // 可直接用于 C 风格接口
}

// ============================================================

/**
 * @brief 迭代器
 */
void demo_iterators()
{
    std::cout << "\n====== 3. 迭代器 ======\n";

    std::vector<int> vec = { 1, 2, 3, 4, 5 };

    /* 3.1 普通迭代器 begin/end */
    std::cout << "正向迭代: ";
    for (auto it = vec.begin(); it != vec.end(); it++)
    {
        std::cout << *it << " ";
    }
    std::cout << "\n";

    /* 3.2 const 迭代器 cbegin/cend (C++ 11) */
    std::cout << "const 迭代: ";
    for (auto it = vec.cbegin(); it != vec.cend(); it++)
    {
        std::cout << *it << " ";
    }
    std::cout << "\n";

    /* 3.3 反向迭代器 rbegin/rend */
    std::cout << "反向迭代: ";
    for (auto it = vec.rbegin(); it != vec.rend(); it++)
    {
        std::cout << *it << " ";
    }
    std::cout << "\n";

    /* 3.4 const 反向迭代器 crbegin/crend (C++ 11) */
    std::cout << "const 反向: ";
    for (auto it = vec.crbegin(); it != vec.crend(); it++)
    {
        std::cout << *it << " ";
    }
    std::cout << "\n";

    /* 3.5 范围 for 循环(底层基于迭代器) */
    std::cout << "范围 for: ";
    for (int x : vec)
    {
        std::cout << x << " ";
    }
    std::cout << "\n";

    /*
     * 3.6 迭代器失效说明:
     * - insert / push_bash 可能导致所有迭代器失效(重新分配内存时)
     * - erase 导致被删位置及之后的迭代器失效
     * - 仅在尾部插入/删除且不扩容时,尾前迭代器可能保持有效
     */
}

// ============================================================

/**
 * @brief 容量操作
 */
void demo_capacity()
{
    std::cout << "\n====== 4. 容量操作 ======\n";

    std::vector<int> vec;
    std::cout << "初始空 vector\n";
    std::cout << "  empty()    = " << std::boolalpha << vec.empty() << "\n";
    std::cout << "  size()     = " << vec.size() << "\n";
    std::cout << "  capacity() = " << vec.capacity() << "\n";
    std::cout << "  max_size() = " << vec.max_size() << "\n";

    /* 4.1 reserve: 预分配内存,只改capacity,不改size */
    vec.reserve(20);
    std::cout << "\nreserve(20) 后:\n";
    std::cout << "  size()     = " << vec.size() << "\n";
    std::cout << "  capacity() = " << vec.capacity() << "\n";

    /* 4.2 push_back 不扩容时迭代器有效 */
    for (int i = 0; i < 10; i++)
    {
        vec.push_back(i);
    }
    print_vector(vec, "push_back 10 个元素");

    /* 4.3 resize: 改变元素个数 */
    vec.resize(15); // 新增元素值初始化
    print_vector(vec, "resize(15) 后");

    vec.resize(20, 99); // 新增元素用99填充
    print_vector(vec, "resize(20, 99) 后");

    vec.resize(5);  // 截断尾部元素
    print_vector(vec, "resize(5) 截断后");

    /* 4.4 shrink_to_fit: 释放多于容量(C++ 11,请求性,不保证) */
    vec.shrink_to_fit();
    std::cout << "shrink_to_fit 后 capacity = " << vec.capacity() << "\n";

    /* 4.5 工程化最佳实践:已知大小时优先 reserve 避免多次扩容 */
    std::vector<int> big_vec;
    big_vec.reserve(1000);  // 一次性分配,避免多次 realloc
    for (int i = 0; i < 1000; i++)
    {
        big_vec.push_back(i);
    }
    std::cout << "预分配 1000 后:size=" << big_vec.size()
        << ", capacity=" << big_vec.capacity() << "\n";
}

// ============================================================

/**
 * @brief 修改操作
 */
void demo_modifiers()
{
    std::cout << "\n====== 5. 修改操作 ======\n";

    /* 5.1 push_back: 尾部插入(拷贝) */
    std::vector<int> vec;
    vec.push_back(1);
    vec.push_back(2);
    vec.push_back(3);
    print_vector(vec, "push_back 三次");

    /* 5.2 emplace_back: 尾部原位构造(C++ 11,避免临时对象) */
    std::vector<Widget> widgets;
    widgets.emplace_back(1, "A");
    widgets.emplace_back(2, "B");
    std::cout << "emplac_back 两个 Widget, size=" << widgets.size() << "\n";

    /* 5.3 pop_back: 尾部删除(不返回值) */
    vec.pop_back();
    print_vector(vec, "pop_back 后");

    /* 5.4 insert: 指定位置插入 */
    auto it = vec.begin() + 1;
    vec.insert(it, 100);    // 单个元素
    print_vector(vec, "insert 单个 100");

    it = vec.begin();
    vec.insert(it, 3, 50);  // n 个相同元素
    print_vector(vec, "insert 3 个 50");

    int arr[] = { 7, 8, 9 };
    vec.insert(vec.end(), std::begin(arr), std::end(arr)); // 迭代器范围
    print_vector(vec, "insert 数组范围");

    vec.insert(vec.begin(), { 101, 102 });  // 初始化列表
    print_vector(vec, "insert 初始化列表");

    /* 5.5 emplace: 指定位置原位构造(C++ 11) */
    std::vector<Widget> wvec;
    wvec.emplace_back(10, "X");
    wvec.emplace(wvec.begin(), 20, "Y");
    print_vector(wvec, "wvec");
    std::cout << "emplace 后 Widget 数量: " << wvec.size() << "\n";

    /* 5.6 erase: 删除指定位置元素 */
    auto v_it = vec.begin() + 2;
    vec.erase(v_it);
    print_vector(vec, "erase 第 3 个元素");

    /* 5.7 erase: 范围删除 [first, last) */
    vec.erase(vec.begin() + 1, vec.begin() + 4);
    print_vector(vec, "erase 范围 [1,4)");

    /* 5.8 clear: 清空所有元素,capacity不变 */
    vec.clear();
    std::cout << "clear 后: size=" << vec.size()
        << ", capacity=" << vec.capacity() << "\n";

    /* 5.9 swap: 交换两个 vector 内容(O(1),只交换内部指针) */
    std::vector<int> a = { 1, 2, 3 };
    std::vector<int> b = { 10, 20, 30, 40, 50 };
    print_vector(a, "交换前 a");
    print_vector(b, "交换前 b");
    a.swap(b);
    print_vector(a, "交换前 a");
    print_vector(b, "交换前 b");

    /* 5.10 利用 swap 前置释放内存(经典技巧) */
    std::vector<int> huge(10000);
    std::cout << "huge 容量: " << huge.capacity() << "\n";
    huge.clear();
    std::cout << "clear 后容量: " << huge.capacity() << "\n";
    std::vector<int>().swap(huge);  // 临时空 vector 交换
    std::cout << "swap 释放后容量: " << huge.capacity() << "\n";
}

// ============================================================

/**
 * @brief 与 STL 算法配合
 */
void demo_algorithms()
{
    std::cout << "\n====== 6. STL 算法配合 ======\n";

    std::vector<int> vec = { 5, 2, 8, 1, 9, 3, 7, 4, 6 };
    print_vector(vec, "原始 vec");

    /* 6.1 sort: 排序 */
    std::sort(vec.begin(), vec.end());
    print_vector(vec, "sort 升序");

    std::sort(vec.rbegin(), vec.rend());
    print_vector(vec, "sort 降序");

    /* 6.2 find: 查找元素 */
    auto it = std::find(vec.begin(), vec.end(), 7);
    if (it != vec.end())
    {
        std::cout << "找到 7,下标: " << std::distance(vec.begin(), it) << "\n";
    }

    /* 6.3 find_if: 条件查找 */
    it = std::find_if(vec.begin(), vec.end(), [](int x) { return x < 3; });
    if (it != vec.end())
    {
        std::cout << "找到第一个小于 3 的数: " << *it << "\n";
    }

    /* 6.4 count / count_if: 计数 */
    int cnt = std::count(vec.begin(), vec.end(), 5);
    std::cout << "5 出现次数: " << cnt << "\n";

    int even_cnt = std::count_if(vec.begin(), vec.end(),
        [](int x) { return x % 2 == 0; });
    std::cout << "偶数个数: " << even_cnt << "\n";

    /* 6.5 for_each: 遍历 */
    std::cout << "for_each 输出: ";
    std::for_each(vec.begin(), vec.end(), [](int& x) {std::cout << x << " "; });
    std::cout << "\n";

    /* 6.6 transform: 变换 */
    std::vector<int> out;
    out.reserve(vec.size());
    std::transform(vec.begin(), vec.end(), std::back_inserter(out), [](int x) {return x * 2; });
    print_vector(out, "transform 乘 2");

    /* 6.7 accumulate: 累加(numeric) */
    int sum = std::accumulate(vec.begin(), vec.end(), 0);
    std::cout << "累加和: " << sum << "\n";

    /* 6.8 unique + erase: 去重经典写法 */
    std::vector<int> dup = { 1, 2, 3, 3, 3, 4, 5, 5 };
    std::sort(dup.begin(), dup.end());
    auto last = std::unique(dup.begin(), dup.end());
    dup.erase(last, dup.end());
    print_vector(dup, "去重后");

    /* 6.9 lower_bound / upper_bound (需有序) */
    std::sort(vec.begin(), vec.end());
    auto lb = std::lower_bound(vec.begin(), vec.end(), 5);
    std::cout << "lower_bound(5) 指向: " << *lb << "\n";

    /* 6.10 reverse: 反转 */
    std::reverse(vec.begin(), vec.end());
    print_vector(vec, "reverse 后");

    /* 6.11 remove / remove_if + erase: 删除-擦除惯用法 */
    std::vector<int> nums = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
    // 删除所有偶数
    nums.erase(std::remove_if(nums.begin(), nums.end(), [](int x) {return x % 2 == 0; }),
        nums.end());
    print_vector(nums, "删除所有偶数后");

    /* 6.12 std::erase / std::erase_if (C++ 20,成员级别的便捷函数) */
#if __cplusplus >= 202002L
    std::vector<int> v20 = { 1, 2, 3, 2, 4, 2, 5 };
    std::erase(v20, 2); // 删除所有值为2的元素
    print_vector(v20, "C++ 20 std::erase(2)");

    std::erase_if(v20, [](int x) { return x > 3; });
    print_vector(v20, "C++ 20 std::erase_if(>3)");
#endif
}

// ============================================================

/**
 * @brief 非成员函数与比较
 */
void demo_non_member()
{
    std::cout << "\n====== 7. 非成员函数与比较 ======\n";

    std::vector<int> a = { 1, 2, 3 };
    std::vector<int> b = { 1, 2, 3 };
    std::vector<int> c = { 1, 2, 4 };

    /* 7.1 比较运算符(按字典序逐元素比较) */
    std::cout << std::boolalpha;
    std::cout << "a == b : " << (a == b) << "\n";
    std::cout << "a != c : " << (a != c) << "\n";
    std::cout << "a <  c : " << (a < c) << "\n";
    std::cout << "a <= b : " << (a <= b) << "\n";
    std::cout << "c >  a : " << (c > a) << "\n";
    std::cout << "c >= b : " << (c >= b) << "\n";

    /* 7.2 std::swap 非成员版本(ADL 优先调用成员 swap) */
    std::swap(a, c);
    print_vector(a, "std::swap 后 a");
    print_vector(c, "std::swap 后 c");
}

// ============================================================

/**
 * @brief 二维 vector 与嵌套
 */
void demo_2d_vector()
{
    std::cout << "\n====== 8. 二维 vector ======\n";

    /* 8.1 初始化 M×N 的二维数组 */
    int rows = 3, cols = 4;
    std::vector<std::vector<int>> matrix(rows, std::vector<int>(cols, 0));

    /* 8.2 赋值 */
    for (int i = 0; i < rows; i++)
    {
        for (int j = 0; j < cols; j++)
        {
            matrix[i][j] = i * cols + j;
        }
    }

    /* 8.3 遍历 */
    std::cout << "3×4 矩阵: \n";
    for (const auto& row : matrix)
    {
        for (int val : row)
        {
            std::cout << val << "\t";
        }
        std::cout << "\n";
    }

    /* 8.4 初始化列表构造二维 */
    std::vector<std::vector<int>> mat2 = {
        {1, 2, 3},
        {4, 5, 6},
        {7, 8, 9}
    };
    std::cout << "初始化列表二维矩阵:\n";
    for (const auto& row : mat2)
    {
        for (int v : row)
        {
            std::cout << v << " ";
        }
        std::cout << "\n";
    }

    /* 8.5 逐行动态 push_back(不规则矩阵 / 锯齿数组) */
    std::vector<std::vector<int>> jagged;
    jagged.push_back({ 1 });
    jagged.push_back({ 2, 3 });
    jagged.push_back({ 4, 5, 6 });
    jagged.push_back({ 7, 8, 9, 10 });
    std::cout << "\njagged (锯齿数组,每行长度不同):\n";
    for (size_t i = 0; i < jagged.size(); ++i)
    {
        std::cout << "  row[" << i << "] (size=" << jagged[i].size() << "):";
        for (int v : jagged[i]) std::cout << v << " ";
        std::cout << "\n";
    }

    /* 8.6 先 reserve 行数,再逐行 emplace_back(性能最优) */
    std::vector<std::vector<int>> mat4;
    mat4.reserve(3);    // 预分配行容量
    for (int i = 0; i < 3; i++)
    {
        std::vector<int> row(4, i * 10);    // 每行 4 列
        mat4.emplace_back(std::move(row));  // 移动语义,避免拷贝
    }
    std::cout << "\nmat4 (reserve + emplace_back):\n";
    for (const auto& row : mat4)
    {
        for (int v : row) std::cout << v << "\t";
        std::cout << "\n";
    }

    /*
     * 注意:二维 vector 每行内存独立分配,行与行之间不连续
     * 如需连续内存的二维数组,可用一维 vector 模拟:
     *      std::vector<int> flat(rows * cols);
     *      flat[i * cols + j] = value;
     */
}

// ============================================================

/**
 * @brief 三维 vector 创建
 */
void demo_3d_vector()
{
    std::cout << "\n====== 9. 三维 vector ======\n";

    /* 9.1 D层 × M行 × N列,初始值为0 */
    int depth = 2, rows = 3, cols = 4;
    std::vector<std::vector<std::vector<int>>> tensor(
        depth,
        std::vector<std::vector<int>>(
            rows,
            std::vector<int>(cols, 0)
        )
    );

    // 填充数据:tensor[d][r][c] = d * 100 + r * 10 + c
    for (int d = 0; d < depth; d++)
    {
        for (int r = 0; r < rows; r++)
        {
            for (int c = 0; c < cols; c++)
            {
                tensor[d][r][c] = d * 100 + r * 10 + c;
            }
        }
    }

    std::cout << "tensor (" << depth << "x" << rows << "x" << cols << "):\n";
    for (int d = 0; d < depth; d++)
    {
        std::cout << "  layer[" << d << "]:\n";
        for (int r = 0; r < rows; r++)
        {
            std::cout << "    ";
            for (int c = 0; c < cols; c++)
            {
                std::cout << tensor[d][r][c] << "\t";
            }
            std::cout << "\n";
        }
    }

    /* 9.2 初始化列表直接构造 */
    std::vector<std::vector<std::vector<int>>> tensor2 = {
        {
            {1, 2},
            {3, 4}
        },
        {
            {5, 6},
            {7, 8}
        }
    };
    std::cout << "\ntensor2 (初始化列表 2×2×2):\n";
    for (size_t d = 0; d < tensor2.size(); d++)
    {
        std::cout << "  layer[" << d << "]:\n";
        for (const auto& row : tensor2[d])
        {
            std::cout << "    ";
            for (int v : row) std::cout << v << " ";
            std::cout << "\n";
        }
    }

    /* 9.3 逐层逐行构建(适用于运行时确定维度的场景) */
    std::vector<std::vector<std::vector<int>>> tensor3;
    tensor3.reserve(2); // 预分配层数
    for (int d = 0; d < 2; d++)
    {
        std::vector<std::vector<int>> layer;
        layer.reserve(3);
        for (int r = 0; r < 3; r++)
        {
            std::vector<int> row(2, d * 10 + r);
            layer.emplace_back(std::move(row));
        }
        tensor3.emplace_back(std::move(layer));
    }
    std::cout << "\ntensor3 (逐层 reserve + emplace_back):\n";
    for (size_t d = 0; d < tensor3.size(); d++)
    {
        std::cout << "  layer[" << d << "]:\n";
        for (const auto& row : tensor3[d])
        {
            std::cout << "    ";
            for (int v : row) std::cout << v << " ";
            std::cout << "\n";
        }
    }

    /*
     * 建议:
     *  - 三维及以上 vector 嵌套层次深,可读性差,内存碎片多
     *  - 推荐封装为一维 vector + 多维索引计算:
     *      std::vector<int> flat(depth * rows * cols);
     *      flat[(d * rows + r) * cols + c] = value;
     *  - 或使用第三方库(如 Eigen、xtensor)处理多维数组
     */
}

// ============================================================

/**
 * @brief 工程化注意事项与最佳实践
 */
void demo_best_practices()
{
    std::cout << "\n====== 10. 工程化最佳实践 ======\n";

    /*
     * 10.1 传参规范
     *      - 只读: const std::vector<T>&
     *      - 写入: std::vector<T>&
     *      - 转移所有权: std::vector<T>&& 或直接传值
     */

     /* 10.2 reserve 预分配,避免多次扩容(性能敏感场景) */
    std::vector<int> v;
    v.reserve(100);
    for (int i = 0; i < 100; i++)
    {
        v.push_back(i);
    }
    std::cout << "reserve 后 100 元素: capacity=" << v.capacity() << "\n";

    /* 10.3 自定义类型优先 emplace_back 而非 push_back(临时对象) */
    std::vector<Widget> wv;
    wv.reserve(10);
    wv.emplace_back(1, "hello");    // 直接构造,零拷贝
    //wv.push_back(Widget(1, "hello"));   // 构造 + 移动/拷贝

    /* 10.4 range-based for 中修改元素用引用 */
    for (auto& x : v)
    {
        x *= 2;
    }

    /* 10.5 只读遍历用 const 引用 */
    for (const auto& x : v)
    {
        (void)x;    // 使用 x
    }

    /*
     * 10.6 迭代器失效场景注意
     *      - 循环中 erase 必须使用返回值更新迭代器
     */
    std::vector<int> nums = { 1, 2, 3, 4, 5, 6 };
    for (auto it = nums.begin(); it != nums.end(); /* no increment */)
    {
        if (*it % 2 == 0)
        {
            it = nums.erase(it);    // erase 返回下一个有效迭代器
        }
        else
        {
            it++;
        }
    }
    print_vector(nums, "安全循环 erase 后");

    /* 10.7 at() 用于边界不确定场景,operator[] 用于性能关键且边界有保障场景 */

    /* 10.8 shrink_to_fit 仅在内存紧张、vector长期存活且后续不再增长时使用 */
    v.shrink_to_fit();

    std::cout << "工程化要点演示完成\n";
}

// ============================================================

/**
 * @brief bool 特化 (std::vector<bool> 空间优化的位压缩)
 */
void demo_vector_bool()
{
    std::cout << "\n====== 11. vector<bool> 优化 ======\n";

    std::vector<bool> vb = { true, false, true, true, false };
    std::cout << "vector<bool> size = " << vb.size() << "\n";
    /*
     * 注意:sizeof 每个元素不到 1 字节,位存储
     * operator[] 返回代理对象 (proxy reference),不是 bool&
     * 常见坑:不能取地址、auto 推导可能出问题
     */

    vb.flip();  // 全体取反
    std::cout << "flip 后: ";
    for (bool b : vb)
    {
        std::cout << b << " ";
    }
    std::cout << "\n";

    // 工程建议:如不需要极致空间,可用 vector<char> 替代以避免代理引用坑
}

// ============================================================

int main()
{
    std::cout << "========== std::vector 全用法工程化演示 ==========\n";

    demo_constructors();
    demo_element_access();
    demo_iterators();
    demo_capacity();
    demo_modifiers();
    demo_algorithms();
    demo_non_member();
    demo_2d_vector();
    demo_3d_vector();

    demo_best_practices();
    demo_vector_bool();

    std::cout << "\n========== 演示完成 ==========\n";
    return 0;
}
Logo

汇聚全球AI编程工具,助力开发者即刻编程。

更多推荐