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;//输出为2system("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;//输出为2system("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,容量可能不为0std::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;
}