为何C++中reserve后的空vector可访问元素且运行正常?
问题解析:为何这段C++代码能“正常”运行?
有一段C++代码,通过reserve()为vector预分配内存后,直接使用下标赋值(未调用push_back()),虽然size()始终返回0,但却能正确访问并输出元素,代码如下:
#include <iostream> #include <vector> using namespace std; int main(){ unsigned size; cin >> size; vector<unsigned long> nums; nums.reserve(size); for(unsigned i{0}; i < size; ++i) cin >> nums[i]; cout << "length " << nums.size() << '\n'; for(unsigned i{0}; i < size; ++i) cout << i << ' ' << nums[i] << endl; return 0; }
示例输入
3 45 12 1454
示例输出
length 0 0 45 1 12 2 1454
原因解析
reserve()的本质:reserve(n)的作用是为vector预分配可容纳至少n个元素的内存空间,它只会修改vector的capacity()(已分配内存能容纳的最大元素数),但不会改变size()(当前实际存在的元素个数)。所以执行nums.reserve(size)后,nums.size()依然是0,而nums.capacity()至少等于输入的size值。- 下标访问的未定义行为:C++标准规定,当使用
operator[]访问vector时,若索引i >= nums.size(),属于未定义行为。未定义行为不代表一定会报错,它可能因为各种巧合“正常工作”——这次刚好是因为reserve已经提前分配了足够的内存,你写入的数据刚好落在这块预分配的内存里,没有破坏其他程序数据,读的时候也能正确取出。但这种行为完全不可靠,换个编译器、操作系统或者运行环境,程序可能直接崩溃、输出乱码,或者出现其他不可预期的结果。 - 代码的正确写法:要让代码符合C++标准且行为可靠,有两种常见方式:
- 用
resize(size)代替reserve(size):resize会直接修改vector的size,同时初始化对应数量的元素,之后就可以安全地用下标访问赋值。 - 保留
reserve的同时,使用push_back()或emplace_back()逐个添加元素,这样size会随着元素添加正确增长。
- 用
内容的提问来源于stack exchange,提问作者fetis
相关产品推荐
相关产品推荐

