目录
[1. 底层实现:](#1. 底层实现:)
[2. 动态性和静态性:](#2. 动态性和静态性:)
[3. 内存管理:](#3. 内存管理:)
[4. 迭代器和指针:](#4. 迭代器和指针:)
[5. 访问效率:](#5. 访问效率:)
[6. 适用场景:](#6. 适用场景:)
vector
std::vector
是 C++ STL 提供的动态数组容器,提供了多种操作。以下是一些常见的 std::vector
操作,一一列举出来
初始化和基本操作
cpp
std::vector<int> myVector; // 初始化一个空的向量
myVector.push_back(1); // 添加元素到向量末尾
myVector[2] = 10; // 访问和修改向量元素
int size = myVector.size(); // 获取向量大小
插入和删除元素
cpp
myVector.insert(myVector.begin() + 1, 4); // 插入元素到指定位置
myVector.erase(myVector.begin() + 2); // 删除指定位置的元素
myVector.clear(); // 清空向量
范围操作
cpp
std::vector<int> source = {1, 2, 3, 4, 5};
std::vector<int> destination = source; // 复制整个向量
std::vector<int> subVector(source.begin() + 1, source.begin() + 4); // 复制部分向量
元素访问和遍历
cpp
int elementAtIndex2 = myVector[2]; // 使用下标访问元素
// 使用迭代器访问元素
for (std::vector<int>::iterator it = myVector.begin(); it != myVector.end(); ++it) {
// ...
}
// 使用范围-based for 循环
for (const auto& element : myVector) {
// ...
}
其他常用方法
cpp
int firstElement = myVector.front(); // 获取第一个元素
int lastElement = myVector.back(); // 获取最后一个元素
bool isEmpty = myVector.empty(); // 判断向量是否为空
myVector.resize(8); // 改变向量大小
移动语义和右值引用
cpp
std::vector<std::string> source = {"apple", "orange", "banana"};
std::vector<std::string> destination(std::make_move_iterator(source.begin()), std::make_move_iterator(source.end()));
使用迭代器进行插入和删除
cpp
std::vector<int>::iterator it = myVector.begin() + 2;
myVector.insert(it, 10); // 在指定位置插入元素
myVector.erase(it + 3); // 在指定位置删除元素
在特定条件下删除元素
cpp
myVector.erase(std::remove(myVector.begin(), myVector.end(), 3), myVector.end());
使用函数对象进行元素变换
cpp
struct Square {
int operator()(int x) const {
return x * x;
}
};
std::transform(myVector.begin(), myVector.end(), myVector.begin(), Square());
使用 std::find
查找元素
cpp
int searchElement = 5;
auto it = std::find(myVector.begin(), myVector.end(), searchElement);
if (it != myVector.end()) {
// 元素找到的处理
}
排序向量
cpp
std::sort(myVector.begin(), myVector.end());
反向遍历向量
cpp
// 使用逆向迭代器
for (auto it = myVector.rbegin(); it != myVector.rend(); ++it) {
// ...
}
查找最小和最大元素
cpp
auto minElement = std::min_element(myVector.begin(), myVector.end());
auto maxElement = std::max_element(myVector.begin(), myVector.end());
计算向量的和
cpp
int sum = std::accumulate(myVector.begin(), myVector.end(), 0);
使用 lambda 表达式进行元素变换
cpp
// 将所有元素加倍
std::transform(myVector.begin(), myVector.end(), myVector.begin(), [](int x) { return x * 2; });
使用 std::copy
复制向量
cpp
std::vector<int> copyVector;
std::copy(myVector.begin(), myVector.end(), std::back_inserter(copyVector));
将向量转为数组
cpp
int* arrayData = myVector.data();
遍历并修改所有元素
cpp
for (auto& element : myVector) {
element *= 2;
}
使用自定义比较函数进行排序
cpp
// 按照元素的绝对值进行升序排序
std::sort(myVector.begin(), myVector.end(), [](int a, int b) {
return std::abs(a) < std::abs(b);
});
使用 std::reverse
反转向量
cpp
std::reverse(myVector.begin(), myVector.end());
list
- 初始化和基本操作:
cpp
#include <list>
std::list<int> myList; // 初始化一个空的列表
std::list<int> myList2 = {1, 2}; // 使用初始化列表初始化列表
myList.push_back(3); // 在列表末尾添加元素
myList.push_front(2); // 在列表开头添加元素
int frontElement = myList.front(); // 获取列表第一个元素
int backElement = myList.back(); // 获取列表最后一个元素
myList.pop_back(); // 删除列表末尾的元素
myList.pop_front(); // 删除列表开头的元素
- 插入和删除元素:
cpp
#include <list>
std::list<int> myList = {1, 2, 3, 4};
auto it = myList.begin();
++it; // 移动到第二个元素的位置
myList.insert(it, 5); // 在指定位置插入元素
myList.erase(it); // 删除指定位置的元素
myList.remove(3); // 删除列表中所有值为3的元素
myList.clear(); // 清空列表
- 迭代器和遍历:
cpp
#include <list>
std::list<int> myList = {1, 2, 3, 4};
// 使用迭代器遍历列表
for (std::list<int>::iterator it = myList.begin(); it != myList.end(); ++it) {
// ...
}
// 使用范围-based for 循环
for (const auto& element : myList) {
// ...
}
- 查找和替换:
cpp
#include <list>
#include <algorithm>
std::list<int> myList = {1, 2, 3, 4};
auto it = std::find(myList.begin(), myList.end(), 3); // 查找元素
if (it != myList.end()) {
// 元素找到的处理
}
myList.unique(); // 删除相邻重复元素
- 合并和拆分:
cpp
#include <list>
std::list<int> myList1 = {1, 3, 5};
std::list<int> myList2 = {2, 4, 6};
myList1.merge(myList2); // 合并两个已排序的列表
std::list<int> newList;
auto it = std::find(myList1.begin(), myList1.end(), 3);
newList.splice(newList.begin(), myList1, it, myList1.end()); // 从一个列表移动元素到另一个列表
- 使用自定义类型:
cpp
#include <list>
#include <iostream>
// 自定义类型
struct Person {
std::string name;
int age;
};
int main() {
// 使用自定义类型的列表
std::list<Person> people = {{"Alice", 25}, {"Bob", 30}, {"Charlie", 22}};
// 访问和修改自定义类型的列表元素
auto it = people.begin();
it->age = 32;
// 迭代自定义类型的列表元素
for (const auto& person : people) {
std::cout << person.name << " - " << person.age << " years old" << std::endl;
}
return 0;
}
- 将列表转为数组:
cpp
#include <list>
#include <vector>
std::list<int> myList = {1, 2, 3, 4};
// 将列表转为数组
std::vector<int> myVector(myList.begin(), myList.end());
9. 自定义比较函数进行排序
cpp
#include <list>
#include <algorithm>
#include <iostream>
// 自定义比较函数
bool compare(int a, int b) {
return a > b; // 降序排序
}
int main() {
std::list<int> myList = {3, 1, 4, 1, 5, 9, 2, 6, 5, 3};
// 使用自定义比较函数进行排序
myList.sort(compare);
// 输出排序后的列表元素
for (const auto& element : myList) {
std::cout << element << " ";
}
std::cout << std::endl;
return 0;
}
list和vector的区别
1. 底层实现:
-
std::list
: 使用双向链表实现,每个元素存储下一个元素和前一个元素的地址,因此在插入和删除元素时,效率较高。但是,由于不是连续存储的,随机访问元素的性能较差。 -
std::vector
: 使用动态数组实现,元素在内存中是连续存储的,支持通过索引进行快速的随机访问。但在插入和删除元素时,可能需要移动其他元素,因此效率相对较低。
2. 动态性和静态性:
-
std::list
: 是动态容器,可以在运行时动态增加或删除元素。 -
std::vector
: 是静态容器,其大小在声明时就已经确定,无法动态改变。需要重新分配内存和复制元素才能改变其大小。
3. 内存管理:
-
std::list
: 每个元素都有独立的内存块,插入和删除元素时不需要移动其他元素,因此内存管理较为灵活。但是,由于链表结构,会带来额外的指针开销。 -
std::vector
: 元素在内存中是紧密排列的,随机访问效率高。但插入和删除元素可能需要移动其他元素,导致额外的开销。
4. 迭代器和指针:
std::list
: 提供双向迭代器,支持双向遍历。
cpp
std::list<int>::iterator it = myList.begin();
std::vector
: 提供随机访问迭代器,支持快速的随机访问
cpp
std::vector<int>::iterator it = myVector.begin();
5. 访问效率:
-
std::list
: 随机访问效率较低,因为需要沿着链表逐个移动。但在插入和删除元素时,std::list
的性能较好,尤其是在中间位置。 -
std::vector
: 允许通过索引进行快速的随机访问,因为元素在内存中是连续存储的。然而,在中间插入或删除元素时可能涉及元素的移动,效率较低。
6. 适用场景:
-
std::list
: 适用于频繁的插入和删除操作,以及在序列中间位置进行操作的场景。 -
std::vector
: 适用于需要高效随机访问的场景,以及在序列末尾进行插入和删除操作的场景。
选择使用 std::list
还是 std::vector
取决于具体的使用场景和操作需求。需要根据插入、删除、访问等操作的频率和性能要求来选择合适的容器