C++学习笔记-动态数组(vector)

std::vector是C++标准库中的动态数组容器,它可以自动调整大小,提供了比原始数组更安全和便利的接口。vector在Java中的对应实现应该叫ArrayList。

vector的基本使用

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
#include <iostream>
#include <vector>

struct Vertex
{
    float x, y, z;
    
    Vertex(float x, float y, float z) : x(x), y(y), z(z) {}
};

std::ostream& operator<<(std::ostream& ostream, const Vertex& vertex)
{
    ostream << vertex.x << ", " << vertex.y << ", " << vertex.z;
    return ostream;
}

int main()
{
    std::vector<Vertex> vertices;  // <>中指定存储元素的类型

    /* 向Vector中添加元素 */
    vertices.push_back(Vertex(1, 2, 3));
    vertices.push_back(Vertex(4, 5, 6));

    // 使用下标访问元素
    for (int i = 0; i < vertices.size(); i++)
        std::cout << vertices[i] << std::endl;

    // 删除第二个元素
    vertices.erase(vertices.begin() + 1);

    // 使用范围for循环
    for (const Vertex& v : vertices)
        std::cout << v << std::endl;

    vertices.clear();  // 删除所有元素
}

vector的内存管理

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
#include <iostream>
#include <vector>

class Element
{
private:
    int m_Value;
public:
    Element(int value) : m_Value(value)
    {
        std::cout << "Create Element: " << m_Value << std::endl;
    }
    
    Element(const Element& other) : m_Value(other.m_Value)
    {
        std::cout << "Copy Element: " << m_Value << std::endl;
    }
    
    Element(Element&& other) noexcept : m_Value(other.m_Value)
    {
        std::cout << "Move Element: " << m_Value << std::endl;
    }
    
    ~Element()
    {
        std::cout << "Destroy Element: " << m_Value << std::endl;
    }
    
    int GetValue() const { return m_Value; }
};

int main()
{
    std::cout << "=== Creating vector ===" << std::endl;
    std::vector<Element> vec;
    
    std::cout << "\n=== Adding first element ===" << std::endl;
    vec.push_back(Element(1));  // 创建临时对象,然后移动到vector中
    
    std::cout << "\n=== Adding second element ===" << std::endl;
    vec.push_back(Element(2));  // 可能触发重新分配,导致第一个元素被复制
    
    std::cout << "\n=== Adding third element ===" << std::endl;
    vec.push_back(Element(3));  // 可能再次触发重新分配
    
    std::cout << "\n=== Vector operations complete ===" << std::endl;
    std::cout << "Vector size: " << vec.size() << std::endl;
    std::cout << "Vector capacity: " << vec.capacity() << std::endl;
    
    std::cout << "\n=== Destroying vector ===" << std::endl;
}

使用reserve优化性能

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
int main()
{
    std::cout << "=== Without reserve ===" << std::endl;
    {
        std::vector<Element> vec1;
        vec1.push_back(Element(1));
        vec1.push_back(Element(2));
        vec1.push_back(Element(3));
    }
    
    std::cout << "\n=== With reserve ===" << std::endl;
    {
        std::vector<Element> vec2;
        vec2.reserve(3);  // 预分配容量,避免重新分配
        vec2.push_back(Element(1));
        vec2.push_back(Element(2));
        vec2.push_back(Element(3));
    }
}

emplace_back vs push_back

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
struct Point
{
    float x, y;
    
    Point(float x, float y) : x(x), y(y)
    {
        std::cout << "Create Point(" << x << ", " << y << ")" << std::endl;
    }
    
    Point(const Point& other) : x(other.x), y(other.y)
    {
        std::cout << "Copy Point(" << x << ", " << y << ")" << std::endl;
    }
    
    Point(Point&& other) noexcept : x(other.x), y(other.y)
    {
        std::cout << "Move Point(" << x << ", " << y << ")" << std::endl;
    }
    
    ~Point()
    {
        std::cout << "Destroy Point(" << x << ", " << y << ")" << std::endl;
    }
};

int main()
{
    std::vector<Point> points;
    points.reserve(4);
    
    std::cout << "=== Using push_back ===" << std::endl;
    points.push_back(Point(1.0f, 2.0f));  // 创建临时对象,然后移动
    points.push_back({3.0f, 4.0f});       // 创建临时对象,然后移动
    
    std::cout << "\n=== Using emplace_back ===" << std::endl;
    points.emplace_back(5.0f, 6.0f);      // 直接在vector内存中构造对象
    points.emplace_back(7.0f, 8.0f);      // 更高效,避免临时对象
    
    std::cout << "\n=== Vector contents ===" << std::endl;
    for (const auto& point : points)
    {
        std::cout << "Point(" << point.x << ", " << point.y << ")" << std::endl;
    }
}

vector的常用操作

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
#include <algorithm>

int main()
{
    std::vector<int> numbers;
    
    // 添加元素
    numbers.push_back(10);
    numbers.push_back(20);
    numbers.push_back(30);
    numbers.emplace_back(40);
    
    // 插入元素
    numbers.insert(numbers.begin() + 1, 15);  // 在位置1插入15
    
    // 访问元素
    std::cout << "First element: " << numbers.front() << std::endl;
    std::cout << "Last element: " << numbers.back() << std::endl;
    std::cout << "Element at index 2: " << numbers[2] << std::endl;
    std::cout << "Element at index 2 (safe): " << numbers.at(2) << std::endl;
    
    // 大小和容量
    std::cout << "Size: " << numbers.size() << std::endl;
    std::cout << "Capacity: " << numbers.capacity() << std::endl;
    std::cout << "Empty: " << (numbers.empty() ? "Yes" : "No") << std::endl;
    
    // 遍历
    std::cout << "All elements: ";
    for (size_t i = 0; i < numbers.size(); ++i)
    {
        std::cout << numbers[i] << " ";
    }
    std::cout << std::endl;
    
    // 范围for循环
    std::cout << "Using range-for: ";
    for (const int& num : numbers)
    {
        std::cout << num << " ";
    }
    std::cout << std::endl;
    
    // 迭代器
    std::cout << "Using iterators: ";
    for (auto it = numbers.begin(); it != numbers.end(); ++it)
    {
        std::cout << *it << " ";
    }
    std::cout << std::endl;
    
    // 查找元素
    auto found = std::find(numbers.begin(), numbers.end(), 20);
    if (found != numbers.end())
    {
        std::cout << "Found 20 at position: " << (found - numbers.begin()) << std::endl;
    }
    
    // 删除元素
    numbers.erase(numbers.begin() + 2);  // 删除索引2的元素
    numbers.pop_back();                  // 删除最后一个元素
    
    // 清空
    numbers.clear();
    std::cout << "After clear, size: " << numbers.size() << std::endl;
}

vector的初始化方式

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
int main()
{
    // 默认构造
    std::vector<int> vec1;
    
    // 指定大小
    std::vector<int> vec2(5);           // 5个元素,默认值为0
    std::vector<int> vec3(5, 10);       // 5个元素,每个都是10
    
    // 初始化列表
    std::vector<int> vec4{1, 2, 3, 4, 5};
    std::vector<int> vec5 = {10, 20, 30};
    
    // 从其他容器复制
    std::vector<int> vec6(vec4);        // 拷贝构造
    std::vector<int> vec7 = vec4;       // 拷贝构造
    
    // 从迭代器范围构造
    std::vector<int> vec8(vec4.begin(), vec4.end());
    
    // 移动构造
    std::vector<int> vec9 = std::move(vec4);
    
    // 打印各个vector的内容
    auto printVector = [](const std::vector<int>& v, const std::string& name) {
        std::cout << name << ": ";
        for (int val : v) std::cout << val << " ";
        std::cout << "(size: " << v.size() << ")" << std::endl;
    };
    
    printVector(vec1, "vec1");
    printVector(vec2, "vec2");
    printVector(vec3, "vec3");
    printVector(vec4, "vec4");
    printVector(vec5, "vec5");
    printVector(vec6, "vec6");
    printVector(vec7, "vec7");
    printVector(vec8, "vec8");
    printVector(vec9, "vec9");
}

二维vector

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
int main()
{
    // 创建二维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});
    
    // 方式2:预分配大小
    std::vector<std::vector<int>> matrix2(3, std::vector<int>(3, 0));
    
    // 填充matrix2
    int value = 1;
    for (size_t i = 0; i < matrix2.size(); ++i)
    {
        for (size_t j = 0; j < matrix2[i].size(); ++j)
        {
            matrix2[i][j] = value++;
        }
    }
    
    // 打印矩阵
    auto printMatrix = [](const std::vector<std::vector<int>>& m, const std::string& name) {
        std::cout << name << ":" << std::endl;
        for (const auto& row : m)
        {
            for (int val : row)
            {
                std::cout << val << " ";
            }
            std::cout << std::endl;
        }
        std::cout << std::endl;
    };
    
    printMatrix(matrix, "matrix");
    printMatrix(matrix2, "matrix2");
}

vector的性能考虑

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
#include <chrono>

void PerformanceTest()
{
    const size_t SIZE = 1000000;
    
    // 测试不使用reserve
    auto start = std::chrono::high_resolution_clock::now();
    {
        std::vector<int> vec;
        for (size_t i = 0; i < SIZE; ++i)
        {
            vec.push_back(i);
        }
    }
    auto end = std::chrono::high_resolution_clock::now();
    auto duration1 = std::chrono::duration_cast<std::chrono::milliseconds>(end - start);
    
    // 测试使用reserve
    start = std::chrono::high_resolution_clock::now();
    {
        std::vector<int> vec;
        vec.reserve(SIZE);
        for (size_t i = 0; i < SIZE; ++i)
        {
            vec.push_back(i);
        }
    }
    end = std::chrono::high_resolution_clock::now();
    auto duration2 = std::chrono::duration_cast<std::chrono::milliseconds>(end - start);
    
    std::cout << "Without reserve: " << duration1.count() << " ms" << std::endl;
    std::cout << "With reserve: " << duration2.count() << " ms" << std::endl;
    std::cout << "Improvement: " << (double)duration1.count() / duration2.count() << "x" << std::endl;
}

int main()
{
    PerformanceTest();
}

vector与原始数组的对比

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
void ArrayComparison()
{
    // 原始数组
    int rawArray[5] = {1, 2, 3, 4, 5};
    
    // vector
    std::vector<int> vec = {1, 2, 3, 4, 5};
    
    std::cout << "=== Raw Array ===" << std::endl;
    std::cout << "Size: " << sizeof(rawArray) / sizeof(int) << std::endl;
    for (size_t i = 0; i < 5; ++i)
    {
        std::cout << rawArray[i] << " ";
    }
    std::cout << std::endl;
    
    std::cout << "\n=== Vector ===" << std::endl;
    std::cout << "Size: " << vec.size() << std::endl;
    std::cout << "Capacity: " << vec.capacity() << std::endl;
    for (int val : vec)
    {
        std::cout << val << " ";
    }
    std::cout << std::endl;
    
    // vector的优势
    vec.push_back(6);  // 动态添加元素
    vec.resize(10, 0); // 调整大小
    
    std::cout << "After modifications:" << std::endl;
    std::cout << "Size: " << vec.size() << std::endl;
    for (int val : vec)
    {
        std::cout << val << " ";
    }
    std::cout << std::endl;
}

总结

  1. Vector本质:动态数组,可以自动调整大小,Java中的对应实现应该叫ArrayList
  2. 内存管理:当容量不足时,vector会重新分配更大的内存,并复制所有元素
  3. 性能优化
    • 使用reserve()预分配容量,避免频繁重新分配
    • 使用emplace_back()直接在容器内构造对象,避免临时对象
  4. 常用操作:push_back、pop_back、insert、erase、clear等
  5. 访问方式:下标访问、迭代器、范围for循环等多种方式
updatedupdated2025-09-202025-09-20