现在位置: 首页 > C++ 教程 > 正文

C++ <vector> reserve 函数

C++ 容器类 <vector> C++ 容器类 <vector>


reserve 是 vector 中用于预分配内存的重要函数,可以显著提升添加元素的性能。

reserve 是容器类的成员函数,用于预留至少 n 个元素的存储空间。这不会改变容器的大小(size),但会预先分配足够的内存,避免后续添加元素时频繁重新分配。

reserve 是优化 vector 性能的关键函数,特别适合需要添加大量元素的场景。

单词释义reserve 表示"预留",即预先保留足够的空间。


基本语法与参数

reserve 是容器类的成员函数,需要指定要预留的元素数量。

语法格式

void reserve(size_type n);

参数说明

  • 参数n
    • 类型: size_type(无符号整数类型,通常是 size_t
    • 描述: 你希望预留的最小元素数量。容器将至少分配能够容纳 n 个元素的内存空间。

函数说明

  • 返回值void(无返回值)。
  • 效果: 容器会重新分配内存,使其容量至少为 n。容器的 size() 不会改变,仍是原来的元素数量。
  • 注意: 如果 n 小于当前的容量,reserve 不会做任何事情。如果 n 大于当前容量,会重新分配内存。

实例

让我们通过一系列例子,彻底掌握 reserve 的用法。

示例 1:基础用法 - 预分配空间

实例

#include <iostream>
#include <vector>

int main() {
    // 创建空 vector
    std::vector<int> numbers;

    std::cout << "初始状态 - size: " << numbers.size()
              << ", capacity: " << numbers.capacity() << std::endl;

    // 预留 100 个元素的空间
    numbers.reserve(100);

    std::cout << "reserve(100) 后 - size: " << numbers.size()
              << ", capacity: " << numbers.capacity() << std::endl;

    // 添加元素
    for(int i = 0; i < 10; ++i) {
        numbers.push_back(i);
    }

    std::cout << "添加 10 个元素后 - size: " << numbers.size()
              << ", capacity: " << numbers.capacity() << std::endl;

    return 0;
}

运行结果预期:

初始状态 - size: 0, capacity: 0
reserve(100) 后 - size: 0, capacity: 100
添加 10 个元素后 - size: 10, capacity: 100

代码解析:

  1. reserve(100) 预先分配了能容纳 100 个元素的内存空间。
  2. size() 仍然是 0,因为还没有添加元素。
  3. 添加 10 个元素后,容量仍然是 100,没有发生内存重新分配。

示例 2:使用 reserve 优化大量数据添加

对于需要添加大量元素的场景,预先使用 reserve 可以显著提升性能。

实例

#include <iostream>
#include <vector>
#include <chrono>

int main() {
    const int N = 100000;

    // 不使用 reserve
    std::vector<int> v1;
    auto start1 = std::chrono::high_resolution_clock::now();
    for(int i = 0; i < N; ++i) {
        v1.push_back(i);
    }
    auto end1 = std::chrono::high_resolution_clock::now();
    auto duration1 = std::chrono::duration_cast<std::chrono::microseconds>(end1 - start1);

    // 使用 reserve
    std::vector<int> v2;
    v2.reserve(N);
    auto start2 = std::chrono::high_resolution_clock::now();
    for(int i = 0; i < N; ++i) {
        v2.push_back(i);
    }
    auto end2 = std::chrono::high_resolution_clock::now();
    auto duration2 = std::chrono::duration_cast<std::chrono::microseconds>(end2 - start2);

    std::cout << "不使用 reserve 耗时: " << duration1.count() << " 微秒" << std::endl;
    std::cout << "使用 reserve 耗时: " << duration2.count() << " 微秒" << std::endl;
    std::cout << "性能提升: " << (double)duration1.count() / duration2.count() << "x" << std::endl;

    return 0;
}

代码解析:

  • 添加 100000 个元素时,预先使用 reserve 可以显著减少内存重新分配的次数。
  • 这在处理大量数据时能带来明显的性能提升。

示例 3:使用 reserve 的正确方式

要充分发挥 reserve 的作用,应该预先估计需要的容量。

实例

#include <iostream>
#include <vector>

int main() {
    // 假设我们要存储 1000 个用户的数据
    struct User {
        std::string name;
        int age;
    };

    std::vector<User> users;
    users.reserve(1000); // 预先分配空间

    // 模拟加载用户数据
    for(int i = 0; i < 1000; ++i) {
        User u;
        u.name = "用户" + std::to_string(i);
        u.age = 20 + (i % 50);
        users.push_back(u);
    }

    std::cout << "用户数量: " << users.size() << std::endl;
    std::cout << "容量: " << users.capacity() << std::endl;

    return 0;
}

代码解析:

  • 对于已知大小的数据加载,预先使用 reserve 是最佳实践。
  • 这避免了多次内存重新分配,提高了效率。

示例 4:避免不必要的 reserve

reserve 应该根据实际需要使用,过度预分配会浪费内存。

实例

#include <iostream>
<vector>

int main() {
    // 错误的做法:过度预分配
    std::vector<int> v1;
    v1.reserve(1000000); // 只需要 10 个元素,却预分配了 100 万的空间!

    for(int i = 0; i < 10; ++i) {
        v1.push_back(i);
    }

    std::cout << "只需要 10 个元素 - size: " << v1.size()
              << ", capacity: " << v1.capacity() << std::endl;

    // 正确的做法:按需预分配
    std::vector<int> v2;
    v2.reserve(10);

    for(int i = 0; i < 10; ++i) {
        v2.push_back(i);
    }

    std::cout << "需要 10 个元素 - size: " << v2.size()
              << ", capacity: " << v2.capacity() << std::endl;

    return 0;
}

代码解析:

  • 过度预分配会浪费内存空间。
  • 应该根据实际需要的元素数量来设置 reserve 的参数。

示例 5:reserve 与容量检查

可以在添加元素前检查容量是否足够。

实例

#include <iostream>
#include <vector>

void addElements(std::vector<int>& v, int count) {
    // 如果当前容量不够,预留足够的空间
    if(v.capacity() < v.size() + count) {
        v.reserve(v.size() + count);
    }

    // 添加元素
    for(int i = 0; i < count; ++i) {
        v.push_back(v.size());
    }
}

int main() {
    std::vector<int> data;

    std::cout << "初始 - size: " << data.size()
              << ", capacity: " << data.capacity() << std::endl;

    addElements(data, 50);
    std::cout << "添加 50 个后 - size: " << data.size()
              << ", capacity: " << data.capacity() << std::endl;

    addElements(data, 50);
    std::cout << "再添加 50 个后 - size: " << data.size()
              << ", capacity: " << data.capacity() << std::endl;

    return 0;
}

代码解析:

  • 可以在函数中动态检查并预留容量。
  • 这确保了添加元素时不会发生内存重新分配。

C++ 容器类 <vector> C++ 容器类 <vector>