C++数组大小动态调整技巧:vector与resize应用详解
发布时间: 2024-10-01 05:26:19 阅读量: 47 订阅数: 47
C++ Vector用法详解
5星 · 资源好评率100%
![c++ array](https://media.geeksforgeeks.org/wp-content/uploads/20230302091959/Arrays-in-C.png)
# 1. C++数组与动态内存管理基础
## 1.1 C++数组的本质与特性
C++数组是一种数据结构,它能够存储一系列相同类型的元素。数组中的每个元素都可以通过其索引来访问,索引从0开始。数组的大小必须是编译时常量,这意味着一旦定义,它的大小就不能改变。数组是一个非常基础的内存管理工具,但在处理动态大小的数据时,使用数组可能会引起一些问题,如内存溢出或者内存浪费。
## 1.2 数组与指针的关系
在C++中,数组名可以被解释为指向数组首元素的指针。这一特性使得数组和指针在很多上下文中可以互换使用,但也增加了理解数组操作复杂性。理解数组与指针之间的关系,对于深入学习指针以及动态内存管理是至关重要的。
## 1.3 动态内存分配
C++提供了动态内存分配机制,它允许程序在运行时确定内存大小并进行分配。这种机制主要通过`new`和`delete`关键字实现,让程序员可以更灵活地控制内存。动态内存管理是C++内存管理的基石,但同时也带来了诸如内存泄漏、内存碎片和双重删除等问题。因此,深入理解动态内存分配对于C++开发者来说是必经之路。
为了更有效地管理动态内存,通常推荐使用C++的智能指针类,如`std::unique_ptr`和`std::shared_ptr`,这些智能指针可以自动处理内存释放,减少内存泄漏的风险。
# 2. 深入理解C++标准库中的vector容器
## vector容器的特性与优势
### vector容器的数据结构
`vector`是C++标准模板库(STL)中的一种顺序容器,它实现了一个动态数组。与普通数组不同,`vector`可以动态地增长和缩小,无需在创建时指定固定大小。其内部数据结构在逻辑上表现为一个数组,但在实现上,通常是通过一个指针来管理一块连续的内存区域。
```cpp
#include <iostream>
#include <vector>
int main() {
std::vector<int> vec;
vec.push_back(10); // 动态添加元素
vec.push_back(20);
for (size_t i = 0; i < vec.size(); ++i) {
std::cout << vec[i] << ' ';
}
return 0;
}
```
在上述示例中,`vector`通过`push_back`方法动态地增长。其内部通过指针管理连续内存,便于访问和维护,这使得`vector`在性能上接近原始数组,同时提供了更大的灵活性。
### vector容器的常用操作
`vector`提供了丰富的成员函数来操作内部元素。这些操作包括但不限于插入(`push_back`, `insert`), 删除(`pop_back`, `erase`), 访问(`operator[]`, `at`), 清空(`clear`)和大小管理(`size`, `max_size`, `resize`)等。
```cpp
vec.push_back(30); // 在末尾添加一个元素
vec.insert(vec.begin(), 5); // 在开始位置插入一个元素
int& ref_to_first = vec.front(); // 获取第一个元素的引用
int& ref_to_last = vec.back(); // 获取最后一个元素的引用
vec.erase(vec.begin()); // 删除第一个元素
vec.pop_back(); // 删除最后一个元素
std::cout << "Size of vector: " << vec.size() << std::endl;
vec.resize(5); // 调整大小为5,不足部分用默认值填充或移除多余部分
```
`vector`的这些操作使得数据的管理非常方便,而其提供的一系列迭代器操作则使得与STL算法的集成变得自然和流畅。
## vector的动态扩容机制
### vector内部如何管理内存
`vector`在内部通过一个动态数组管理元素,这通常意味着它维护一个指向连续内存块的指针,以及当前使用空间的大小(`size`)和总分配空间的大小(`capacity`)。
```cpp
std::vector<int> vec;
vec.push_back(10);
vec.push_back(20);
// 指向内部动态数组的指针
int* elements = vec.data();
// vector当前已使用空间大小
size_t current_size = vec.size();
// vector总分配空间大小
size_t total_capacity = vec.capacity();
```
`data()`函数返回指向内部数组的指针,`size()`返回当前元素数量,而`capacity()`则返回为当前`vector`对象预先分配的存储空间容量。
### 动态扩容的时机和策略
当`vector`中存储的元素数量超过当前容量时,`vector`会进行动态扩容,以确保有足够的空间来存储新元素。扩容通常涉及到以下步骤:
1. 分配新的、更大的内存块;
2. 将旧内存块中的元素复制到新内存块中;
3. 销毁旧内存块,并释放其占用的空间;
4. 更新`vector`内部指针,指向新的内存块。
```cpp
std::vector<int> vec;
vec.reserve(100); // 预先分配足够的空间
for (int i = 0; i < 150; ++i) {
vec.push_back(i);
}
std::cout << "Vector size: " << vec.size() << std::endl;
std::cout << "Vector capacity: " << vec.capacity() << std::endl;
```
在上述示例中,尽管插入了150个元素,但预分配了100个元素的空间,因此扩容只会在插入更多元素时触发一次。
## vector与迭代器
### 迭代器的作用与分类
迭代器是一种行为类似于指针的对象,用于访问容器中的元素,而不需要暴露容器的内部实现细节。在C++ STL中,迭代器主要有以下几种类型:
- 输入迭代器 (Input Iterator)
- 输出迭代器 (Output Iterator)
- 前向迭代器 (Forward Iterator)
- 双向迭代器 (Bidirectional Iterator)
- 随机访问迭代器 (Random Access Iterator)
`vector`支持随机访问迭代器,这意味着你可以使用迭代器来访问`vector`中的任何位置的元素,就像使用指针一样。
```cpp
std::vector<int> vec = {1, 2, 3, 4, 5};
std::vector<int>::iterator it = vec.begin(); // 获取迭代器
*it = 10; //
```
0
0