std::vector的疑问
疑问
std::vector 内部大致长这样
class vector {
int* data_;
size_t size_;
size_t capacity_;
}; 请问data_、size_和 capacity_的作用是什么
1. data_
- 作用:指向动态分配的内存的指针。
- 详细解释:
data_是 vector 所有元素的“家”。它指向一块在堆(heap)上通过new[]分配的连续内存空间。vector 的所有元素都顺序存储在这块内存里。因为是指向数组的指针,所以可以通过data_[index]的方式直接访问元素,这与普通数组arr[index]的访问方式完全一致,保证了高效性。 - 示例:对于一个存储了
{1, 2, 3, 4, 5}的 vector,data_指向的内存布局如下:data_ -> [1] [2] [3] [4] [5]
2. size_
- 作用:当前 vector 中实际拥有的元素数量。
- 详细解释:
size_表示用户通过push_back,emplace_back,insert等操作成功添加到 vector 中的元素个数。它是vector::size()方法的返回值。你只能访问和修改索引在[0, size_ - 1]范围内的元素。访问data_[size_]及之后的内存是未定义行为(Undefined Behavior),尽管那块内存可能确实被分配了。 - 示例:继续上面的例子,
size_的值是5。vector[4](即data_[4])是有效的,值为5;而vector[5](即data_[5])是无效的,可能导致程序崩溃。
3. capacity_
- 作用:当前 vector 已分配的内存最多可以容纳的元素数量。
- 详细解释:
capacity_表示data_所指向的那块内存的总容量。为了保证追加元素时的高效(避免每次push_back都重新分配内存),vector 通常会分配比当前所需(size_)更多的内存。capacity_就是这块“预留”内存的边界。它是vector::capacity()方法的返回值。 - 关键关系:
size_ <= capacity_始终成立。 - 示例:当 vector 内部进行扩容时(例如,当前
size_ == capacity_时再次push_back),它会执行以下操作:- 分配一块新的、更大的内存(新容量通常是旧容量的
1.5或2倍)。 - 将旧内存中的所有元素(
[0]到[size_-1])复制或移动到新内存。 - 释放旧内存。
- 让
data_指向新内存。 - 更新
capacity_为新的容量值。 - 然后才执行插入新元素的操作并增加
size_。
- 分配一块新的、更大的内存(新容量通常是旧容量的
总结与类比
你可以用一个搬家的比喻来理解这三者:
data_:就是你新家的地址。capacity_:是你的新家的总面积(例如 100 平方米)。size_:是你已经搬进去的家具数量(例如 60 件)。
| 特性 | data_ (地址) |
size_ (已搬家具数) |
capacity_ (房屋总面积) |
|---|---|---|---|
| 作用 | 定位元素存储位置 | 表示有效元素个数 | 表示内存总容量 |
| 可变性 | 扩容时改变 | 增删元素时改变 | 扩容或 shrink_to_fit 时改变 |
| 访问限制 | 不能直接访问 [size_] 之后 |
索引必须 < size_ |
无直接访问关系 |
| 方法返回 | .data() |
.size() |
.capacity() |
一个简单的过程示例:
vector<int> v;:data_ = nullptr,size_ = 0,capacity_ = 0。v.push_back(1);: 需要扩容。分配(比如)1 个元素的内存。data_= 新地址capacity_ = 1- 存入
1,size_ = 1
v.push_back(2);:size_(1) == capacity_(1),需要再次扩容。分配(比如)2 个元素的新内存。- 将
1复制到新内存 data_= 新新地址capacity_ = 2- 存入
2,size_ = 2
- 将
v.push_back(3);:size_(2) == capacity_(2),继续扩容。分配(比如)4 个元素的新内存。- 将
1, 2复制到新内存 data_= 新新新地址capacity_ = 4- 存入
3,size_ = 3
- 将
此时,状态为:size_ = 3(有3个元素),capacity_ = 4(还能再放1个元素不用扩容)。
浙公网安备 33010602011771号