std::vector的特点
1.在数组末尾添加元素所需的时间是固定的,删除亦是如此
2.在数组中间添加或删除元素所需的时间,和该元素后面的元素个数成正比
3.动态存储
1.实例化vector
实例化vector时,要指定该动态数组中存储的对象类型
std::vector<int> intArray;
std::vector<float> floatArray;
2.使用push_back()在末尾插入元素
std::vector<int> intArray; // 创建一个空的 intArray
// 在末尾添加元素
intArray.push_back(1);
intArray.push_back(2);
intArray.push_back(3);
3.列表初始化
std::vector<int> vec={1,3,5};
4.使用insert()
在指定位置插入元素
插入单个元素
std::vector<int> vec = {1, 2, 4, 5};
auto it = vec.begin() + 2; // 指向索引2的位置,即元素4的迭代器
vec.insert(it, 3); // 在索引2的位置插入元素3,输出为1 2 3 4 5
插入多个相同元素
vec.insert(it, 2, 6); // 在it指向的位置之前插入两个6
//输出结果为1 2 6 6 4 5
将另一个vector的元素插入
std::vector<int> anotherVec = {7, 8, 9};
vec.insert(it, anotherVec.begin(), anotherVec.end());
// 插入anotherVec中的所有元素,输出为1 2 7 8 9 4 5
5.使用数组语法访问vector中的元素
使用下标运算符[]
和成员函数at()
下标运算符[]
#include <iostream>
#include <vector>
int main() {
std::vector<int> vec = {1, 2, 3, 4, 5};
// 访问第二个元素(索引为1)
int secondElement = vec[1];
std::cout <<secondElement<< std::endl;//输出为2
system("pause");
return 0;
}
使用成员函数at()
#include <iostream>
#include <vector>
int main() {
std::vector<int> vec = {1, 2, 3, 4, 5};
// 访问第二个元素(索引为1)
int secondElement = vec.at(1);
std::cout <<secondElement<< std::endl;//输出为2
system("pause");
return 0;
}
PS: 使用下标运算符。若索引超出了当前的元素范围,不会抛出异常,但成员函数at()
会,会抛出 std::out_of_range
异常,因为后者会在运行阶段检查容器的大小
6.使用指针语法(迭代器)访问vector中的元素
vec.begin()
和vec.end()
,与vec.cbegin()
和vec.cend()
的区别
- 可变性: begin() 和 end() 返回的迭代器允许修改元素,而 cbegin() 和 cend()
返回的迭代器不允许修改,只能读取。 - 线程安全: 使用 cbegin() 和 cend() 在多线程环境中通常更安全,因为它们提供的是常量访问,不会改变容器的状态。
- const 正确性: 如果你在一个 const 容器对象上调用 begin() 或 end(),编译器会报错,因为这样违反了 const的约束。在这种情况下,你应该使用 cbegin() 或 cend()。
#include <iostream>
#include <vector>
int main() {
std::vector<int> vec = {1, 2, 3};
// 可变迭代器,允许修改元素
auto it = vec.begin();
*it = 10; // 合法
// 常量迭代器,不允许修改元素
auto cit = vec.cbegin();
// *cit = 20; // 非法,会导致编译错误
const std::vector<int> constVec = {1, 2, 3};
// auto it2 = constVec.begin(); // 非法,会导致编译错误
auto it2 = constVec.cbegin(); // 合法
system("pause");
return 0;
}
7.删除vector中的元素
使用pop_back()
将末尾的元素删除
#include <iostream>
#include <vector>
int main() {
std::vector<int> vec = {1, 2, 3};
auto it=vec.cbegin();
for(auto num:vec){
std::cout<<num<<std::endl;
}
vec.pop_back();
for(auto num:vec){
std::cout<<num<<std::endl;
}
system("pause");
return 0;
}
8.理解大小和容量
1.大小(size): std::vector 的大小指的是容器中实际存储的元素数量,使用size()
函数获取。
2.容量(capacity) std::vector 的容量指的是容器当前分配的内存能够容纳的元素数量的最大值,使用capacity()
函数获取。
#include <iostream>
#include <vector>
int main() {
std::vector<int> vec;
// 初始时,大小为0,容量可能不为0
std::cout << "Size: " << vec.size() << ", Capacity: " << vec.capacity() << std::endl;
// 添加元素
vec.push_back(1);
vec.push_back(2);
// 大小变为2,容量可能增加但大小不会改变
std::cout << "After adding elements, Size: " << vec.size() << ", Capacity: " << vec.capacity() << std::endl;
// 明确设置容量
vec.reserve(100);
// 容量至少为100,大小不变
std::cout << "After reserving capacity, Size: " << vec.size() << ", Capacity: " << vec.capacity() << std::endl;
system("pause");
return 0;
}
9.STL deque类
也是一个STL动态数组类,但支持在数组的开头和末尾插入和删除元素,即提供双端队列的功能。记得添加头文件<deque>
添加元素:
- push_back():在后端添加一个元素。
- push_front():在前端添加一个元素。
删除元素:
- pop_back():删除后端的元素。
- pop_front():删除前端的元素。
#include <iostream>
#include <deque>
int main() {
std::deque<int> dq;
// 在后端添加元素
dq.push_back(10);
dq.push_back(20);
// 在前端添加元素
dq.push_front(5);
// 访问并打印所有元素
for (int num : dq) {
std::cout << num << " ";
}
std::cout << std::endl; // 输出 "5 10 20"
// 删除前端元素
dq.pop_front();
// 删除后端元素
dq.pop_back();
// 再次访问并打印所有元素
for (int num : dq) {
std::cout << num << " ";
}
std::cout << std::endl; // 输出 "10"
system("pause");
return 0;
}