C++ std::vector: vector中元素的存储方式 size、capacity、reserve、resize的使用

1. vector的对象的存储方式

为了支持随机访问,vector将元素连续存储–每个元素紧挨着前一个元素存储。容器中元素是连续存储的,且容器的大小是可变的。

在容器中增加元素时。vector根据存储元素的大小,在内存上申请一个空间,用于存储数据,空间的大小通常会大于所存储元素的实际大小,并且预留出一部分预留的空间,以便再次增加数据时,可以不用重新开辟空间。

当容器再次增加新的元素后,首先判断预留的空间是否够用,如果够用直接在预留空间中存储。如果预留的空间不够,需要在内存中开辟一整块新的更大的空间,并将vector原来的存储的数据拷贝过来,存储到新的内存中,然后在新的内存中增加需要增加的元素,这样保证存储的空间是连续的。所开的空间会预留出一部分空间,以便后续增加数据。

理解了vector的对象的存储方式,很轻松理解size、capacity、reserve、resize的使用。

2. size()和capacity()

size(): 返回vector中存放元素的实际数量( 实际存储元素的个数)。返回值为size_type(无符号整数类型)

capacity(): 返回vector在内存中,开辟空间的容量(最多能放所少个元素)。返回值为size_type(无符号整数类型)

例子:

#include <iostream>
#include <vector>
int main()
{
    std::vector<int> vecInt;
    
    std::cout << vecInt.size() << std::endl;	// 输出的结果为0
    std::cout << vecInt.capacity() << std::endl;	// 输出的结果为0 

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

    std::cout << vecInt.size() << std::endl;	// 输出的结果为10,容器中存了10个元素
    std::cout << vecInt.capacity() << std::endl; // 输出的结果为16,容器在内存开辟空间的容量(包含预留空间)
}

3. reserve()和resize()

reserve(): 在内存上指定容器开辟空间的容量大小。

  • 如果容器目前在内存上开辟空间的容量大于指定的容量,则不做处理直接返回。
  • 如果容器目前在内存上开辟空间的容量小于指定的容量,则在内存上开辟指定容量大小的空间,并将原来的数据拷贝到新的内存中。(相当于容器扩容)

resize():设置容器中的元素。有两个参数,一个参数表示指定元素的数量。另一个可选参数表示,指定元素初始化的值。如果不传入第二个参数,则使用默认值初始化。

  • 如果容器中的元素数量大于resize中设置的值,则将后面多出的元素删除。
  • 如果容器中的元素数量小于resize中设置的值,则在原来的元素后面新增新的元素,如果没有指定值,则按照默认值初始化。

例子:

#include <iostream>
#include <vector>
int main()
{
    std::vector<int> vecInt;

    std::cout << vecInt.size() << std::endl;	// 输出的结果为0
    std::cout << vecInt.capacity() << std::endl;	// 输出的结果为0 

    vecInt.reserve(10);     // 在内存上开辟容量为10的空间
     
    std::cout << vecInt.size() << std::endl;	// 输出的结果为0
    std::cout << vecInt.capacity() << std::endl;	// 输出的结果为10

    vecInt.resize(20,1);    //  将容器初始化20个元素,每个元素的默认值为1

    std::cout << vecInt.size() << std::endl;	// 输出的结果为20,容器中存了20个元素
    std::cout << vecInt.capacity() << std::endl; // 输出的结果为20,容器在内存开辟空间的容量
}

注意: 在执行resize时,如果容器中在内存中,所开的空间不够,会自动扩容。不一定非要执行reserve(),提前开辟空间。在容器中使用其他函数添加元素也是如此。

<think>好的,用户问的是关于std::vectorreserve()方法。首先,我需要确认用户指的是reserve()成员函数,而不是其他可能拼写错误的方法。 接下来,我得回忆一下reserve()的作用。它用于预分配内存,以便在后续添加元素时减少重新分配的次数,提高性能。但要注意,reserve()不会改变vector的大小,只是改变容量。这点很重要,用户可能会和resize()混淆。 然后,用户给出的例子是tmp.reserve(),但括号里没有参数。这可能是用户书写时的疏忽,因为reserve()需要一个参数,即要预留的容量大小。这时候需要提醒用户正确的语法,比如reserve(100)。 还需要解释reserve()的使用场景。比如当知道将要存储大量元素时,提前预留空间可以避免多次内存分配。但也要指出,如果预留过多可能会浪费内存,需要权衡。 另外,要对比reserve()和resize()的区别。resize()会改变vector的大小,新增的元素会被默认初始化,而reserve()只是影响容量,不会增加size()的值。同时,提及size()和capacity()这两个方法的区别,帮助用户理解。 可能用户在实际使用中遇到了性能问题,或者对vector的内存管理机制不太清楚。需要给出示例代码,说明正确用法,并指出常见错误,比如预留后仍然用[]访问,这会导致越界,应该用push_back或emplace_back。 还要注意中英文术语的准确,比如“容量”对应capacity,“大小”对应size。保持语言简洁,结构清晰,分点说明,让用户逐步理解。 最后,检查是否有遗漏点,比如是否提到C++标准中的规定,或者不同编译器实现的差异,但可能用户不需要太深入,保持回答实用为主。</think>关于 `std::vector::reserve()` 的逐步解释: 1. **核心作用** - **预分配内存**:`reserve(n)` 会为 `std::vector` 预先分配至少能容纳 `n` 个元素的内存空间 - **避免重复扩容**:当后续添加元素时,可减少内存重新分配次数,提升性能 - **不改变元素数量**:不会创建/销毁任何元素,`size()` 返回值不变 2. **语法格式** ```cpp void reserve( size_type new_cap ); ``` 正确用法示例: ```cpp std::vector<int> vec; vec.reserve(100); // 预分配至少100个int的内存空间 ``` 3. **典型使用场景** - 已知元素总量时提前优化 - 循环中大量添加元素前 - 需要确保迭代器/指针稳定时(避免内存重分配导致失效) 4. **与 resize() 的对比** | 方法 | 内存分配 | 元素初始化 | size() 变化 | capacity() 变化 | |------------|----------|------------|-------------|------------------| | reserve(n) | 按需分配 | ❌ 不初始化 | 保持原值 | ≥n | | resize(n) | 可能分配 | ✔️ 默认初始化 | 设为n | 可能增加 | 5. **重要注意事项** - **参数有效性**:若 `n <= capacity()`,方法无效果 - **非法访问风险**: ```cpp vec.reserve(100); vec[50] = 42; // 错误!size()仍为0,属于未定义行为 ``` - **正确添加方式**: ```cpp vec.reserve(100); for(int i=0; i<100; ++i){ vec.push_back(i); // 正确,size()逐步增加 } ``` 6. **性能测试示例** ```cpp // 不使用 reserve std::vector<int> v1; for(int i=0; i<1e6; ++i) v1.push_back(i); // 可能触发多次重分配 // 使用 reserve std::vector<int> v2; v2.reserve(1e6); for(int i=0; i<1e6; ++i) v2.push_back(i); // 无重分配 ``` 实测中后者效率通常提高 2-5 倍(取决于元素类型和系统环境) 7. **扩展知识** - **收缩内存**:可通过 `shrink_to_fit()` 释放多余容量 - **容量查询**:`capacity()` 返回当前分配的内存可容纳元素数量 - **C++11 新特性**:`data()` 方法可直接访问底层数组 建议在实际开发中,当元素数量可预估时优先使用 `reserve()`,特别是在处理大规模数据或性能敏感场景下。但需注意避免过度预留造成内存浪费。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值