对vector的总结及详细介绍

本文深入讲解C++中Vector的使用,包括定义、插入、删除、修改元素,以及二维Vector的创建与注意事项。通过实例演示Vector的基本操作,适合初学者及需要复习的开发者。

之前就已经接触过vector,知道这个代表着不定长数组,然后也知道一些常用的用法,碰到别人的题解虽然不熟练但基本都能看得懂,但自己做题目要用到的时候还总是感觉缺了点什么,于是乎从头又认真系统地学了一遍,在这里详细记录下自己的学习心得和总结。
以下所有代码均在DEV5.11环境中编译测试通过。
一、vector是什么
有些时候想开一个数组但却不知道开多大的数组比较好,因为数组的长度可能会有变化,这时候我们就需要运用到动态数组,也就是不定长数组vector。
关于它和动态内存申请的区别,至少vector比较好用吧,说实话。这里留着一个坑,回头系统研究后填上。
二、vector怎么用
①C++中vector头文件就叫vector。
②现在就让我们来定义一个vector动态数组:vector< T > a1;这里定义了一个名称为a1,存储的数据类型为T的动态数组,T可以为常用的int、float、double、long long等标准类型,也可以为自定义类型,例如结构体等。例如我们在这里定义了一个整型动态数组a2:vector< int > a2,值得注意的是,与int a2[90] 不同的是,这里的a2默认为空
③想要在vector动态数组中插入元素要用到自带的push_back操作函数,例如我们要给一个string类型的动态数组s1输入元素,可以如下操作

#include <iostream>
#include <vector>
using namespace std;//STL的调用一般都需要事先声明命名空间,养成好习惯!
int main()
{
	vector<string> s1;
	s1.push_back("CHINA"); //{"CHINA"}
	s1.push_back("England");//{"CHINA","England"}
	s1.push_back("France");//{"CHINA","England","France"}
	return 0}

与此同时我们可以通过size()来获取动态数组的长度,通过类似数组中的[],对vector中的元素进行访问。

#include <iostream>
#include <vector>
using namespace std;//STL的调用一般都需要事先声明命名空间,养成好习惯!
int main()
{
	vector<string> s1;
	s1.push_back("CHINA"); //{"CHINA"}
	s1.push_back("England");//{"CHINA","England"}
	s1.push_back("France");//{"CHINA","England","France"}
	for(int i = 0; i < s1.size(); i++)
	{
		cout << s1[i] << endl;
	}
}

运行结果:在这里插入图片描述
值得注意的是:push_back操作和后面我会写的栈、队列的STL的机理一样,都是将元素插入到最后的,原因是算法复杂度将会因此从O(n)简化为O(1);
当我们要修改某个元素的时候,直接访问用=修改就好了:s1[1] = “America”,即将上程序中写的England替换为了America。代码和运行结果如下:

#include <iostream>
#include <vector>
using namespace std;//STL的调用一般都需要事先声明命名空间,养成好习惯!
int main()
{
	vector<string> s1;
	s1.push_back("CHINA"); //{"CHINA"}
	s1.push_back("England");//{"CHINA","England"}
	s1.push_back("France");//{"CHINA","England","France"}
	s1[1] = "America";//{"CHINA","America","France"}
	for(int i = 0; i < s1.size(); i++)
	{
		cout << s1[i] << endl;
	}
	return 0;
}

在这里插入图片描述
删除元素需要用到pop_back(),与插入一样的是对数组最后面的元素进行操作

#include <iostream>
#include <vector>
using namespace std;//STL的调用一般都需要事先声明命名空间,养成好习惯!
int main()
{
	vector<string> s1;
	s1.push_back("CHINA"); //{"CHINA"}
	s1.push_back("England");//{"CHINA","England"}
	s1.push_back("France");//{"CHINA","England","France"}
	s1[1] = "America";//{"CHINA","America","France"}
	s1.pop_back();//{"CHINA","England"}
	s1.pop_back();//{"CHINA"}
	for(int i = 0; i < s1.size(); i++)
	{
		cout << s1[i] << endl;
	}
	return 0;
}

在这里插入图片描述
清空vector数组需要用的是clear():

#include <iostream>
#include <vector>
using namespace std;//STL的调用一般都需要事先声明命名空间,养成好习惯!
int main()
{
	vector<string> s1;
	s1.push_back("CHINA"); //{"CHINA"}
	s1.push_back("England");//{"CHINA","England"}
	s1.push_back("France");//{"CHINA","England","France"}
	s1.clear();//清空数组内容。
	for(int i = 0; i < s1.size(); i++)
	{
		cout << s1[i] << endl;
	}
	return 0;
}

在这里插入图片描述
值得注意的是,clear()操作清空的只是内容,不是回收了申请的空间!
vector < string >().swap(s1);
用这种方式可以清空动态数组申请的内存。
vector基本方法的总结:

方法功能
push_back();在末尾插入一个元素
pop_back();删除当前末尾的元素
clear清空动态数组的内容(注意是内容)
size()获取当前数组的长度

按照前辈的说法,算法竞赛中能用到的基本操作就是这些了。

④二维vector的定义
二维动态数组的每一维的长度都可以不一样,可以是任意形状的。
借助构造函数,我们可以快速构造一个有n行m个元素的动态数组,每个元素的初始值是 0:
vector <vector < int > > vec2(n, vector< int >(m, 0))。
动态数组的初始化必须要注意类比数组,每一行都是一个不定长度的vector,也就意味着我们必须要注意到非法内存访问的存在。
int n = 10;
vector<vector > vec2;
for (int i = 0; i < n; i++) {
vec2[i].push_back(i);
}
上面的这种写法就是很典型的非法访问内存。
vector的维度可以像数组一样更多,但是超过两维以后操作起来会比较麻烦,所以一般用vector都只到两维。
--------分----------------界---------------线-------------
后面会继续更新。

<think>好的,用户想要详细了解C++中的vector容器。首先,我需要回忆vector的基本概念它在STL中的位置。vector是动态数组,应该对比普通数组的优势,比如动态扩展大小、自动内存管理这些点。用户可能已经知道数组,所以重点要突出vector的不同之处。 接下来,用户可能需要知道如何实际使用vector,所以得包括头文件、初始化方法、常用操作这些内容。比如,如何声明一个vector,push_back、pop_back这些成员函数,还有访问元素的方法,比如用[]或者at()。要强调vector的随机访问特性,O(1)的时间复杂度。 然后,考虑到用户可能关心vector的性能,需要解释它的内存管理机制,比如容量大小,reserveresize的区别,以及插入元素时可能导致的重新分配迭代器失效的问题。这部分可能比较复杂,需要用例子说明,比如当vector容量不足时,会重新分配更大的内存,复制元素,并释放旧内存,这样迭代器就会失效。 另外,用户可能想知道vector的适用场景,比如需要频繁随机访问、在尾部添加或删除元素,而不太适合在中间或头部插入删除的情况。这时候可以对比list或者其他容器,帮助用户理解何时选择vector更合适。 还要注意常见的问题,比如越界访问,虽然operator[]不检查边界,但at()会抛出异常,这一点需要提醒用户注意安全性。此外,C++11引入的emplace_back移动语义可能也是值得提及的优化点。 最后,可能要给一个完整的代码示例,展示vector的基本用法,从包含头文件到遍历元素,这样用户可以直观地看到如何在实际中使用vector。检查有没有遗漏的重要特性,比如swap方法、clear、empty等成员函数,或者C++17的新特性,比如emplace返回迭代器这些。 需要确保回答结构清晰,分点说明,并且语言简洁易懂,避免过于技术化的术语,但又要准确。同时,用户可能希望了解vector的底层实现机制,所以简要说明其动态数组的本质,以及内存增长的策略,比如每次扩容可能是翻倍,但具体实现可能不同。这样用户能理解为什么vector在尾部添加元素的平均时间复杂度是O(1)。 总结下来,回答应该涵盖定义、特性、基本操作、内存管理、性能特点、适用场景以及示例代码,同时指出注意事项最佳实践。这样用户能够全面了解vector容器,并知道如何正确使用它。</think>以下是对C++ `vector` 容器的详细介绍,采用分步说明示例演示: ### 一、基本定义 `vector` 是C++标准模板库(STL)中的序列容器,本质是动态数组: - 底层实现:连续内存空间存储元素 $$T* data$$ - 核心特性:自动管理内存,支持动态扩容 - 头文件:`#include <vector>` ### 二、核心特性 1. **动态扩展** - 初始容量自动分配(通常实现为0) - 当`size() == capacity()`时自动扩容(常见策略:容量翻倍) - 扩容时间复杂度:均摊$O(1)$ 2. **迭代器支持** ```cpp vector<int>::iterator it = vec.begin(); vector<int>::const_iterator cit = vec.cbegin(); ``` 3. **元素访问** ```cpp vec[0]; // 不检查越界(O(1)) vec.at(0); // 越界抛出out_of_range异常(O(1)) vec.front(); // 首元素 vec.back(); // 末元素 ``` ### 三、常用操作 #### 1. 初始化 ```cpp vector<int> vec1; // 空vector vector<int> vec2(5); // 5个0 vector<int> vec3(5, 10); // 5个10 vector<int> vec4{1,2,3}; // 初始化列表 vector<int> vec5(vec4.begin(), vec4.end()); // 迭代器范围 ``` #### 2. 增删元素 ```cpp vec.push_back(10); // 尾部插入(可能触发扩容) vec.emplace_back(10); // C++11更高效的构造插入 vec.pop_back(); // 删除尾部元素(O(1)) vec.insert(vec.begin()+2, 5); // 在指定位置插入(O(n)) vec.erase(vec.begin()+1); // 删除指定位置元素(O(n)) ``` #### 3. 容量控制 ```cpp vec.size(); // 实际元素数量 vec.capacity(); // 当前分配的内存容量 vec.empty(); // 判断是否为空 vec.reserve(100); // 预分配空间(避免多次扩容) vec.resize(10); // 修改元素数量 vec.shrink_to_fit();// 请求释放多余内存(非强制) ``` ### 四、内存特性 1. **内存连续性** ```cpp &vec[0] + i == &vec[i] // 保证地址连续性 ``` 2. **扩容规则** - 典型实现:新容量 = max(2*旧容量, 需求容量) - 扩容后所有迭代器、指针、引用失效 ### 五、复杂度分析 | 操作 | 时间复杂度 | |-------------------|------------| | 随机访问 | $O(1)$ | | 尾部插入/删除 | 均摊$O(1)$ | | 头部/中间插入删除 | $O(n)$ | ### 六、应用场景 - ✅ 需要随机访问元素 - ✅ 主要操作在序列尾部进行 - ✅ 需要内存连续性(如与C API交互) - ❌ 频繁在头部/中间插入删除(建议用`list`) ### 七、完整示例 ```cpp #include <iostream> #include <vector> int main() { std::vector<int> nums = {2,3,4}; nums.insert(nums.begin(), 1); // 头部插入 nums.reserve(10); // 预分配空间 nums.push_back(5); // 遍历方式 for(auto& num : nums) { // 范围for循环 std::cout << num << " "; } return 0; } ``` 输出结果:`1 2 3 4 5` ### 八、注意事项 1. 插入/删除操作可能导致迭代器失效 2. `operator[]`不检查越界,`at()`更安全但性能略低 3. C++11起支持移动语义,可高效转移资源 4. 与数组互操作: ```cpp int arr[5]; std::vector<int> vec(arr, arr+5); // 数组转vector ``` 通过合理使用`vector`,可以显著提升开发效率,但需注意其扩容机制带来的性能影响。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值