C++ 中 std::vector
容器的操作总结如下:
声明与初始化
-
定义空向量:
std::vector<int> vec; // 空的整数向量
-
初始化为一组值:
std::vector<int> vec = {1, 2, 3, 4, 5}; // 初始化为五个整数值
-
指定大小并初始化:
std::vector<int> vec(10, 0); // 创建一个包含10个零的向量
插入元素
-
尾部插入:
vec.push_back(6); // 在向量末尾添加一个元素
-
emplace和push_back的区别:
两者的主要区别在于元素构造和拷贝(或移动)的方式:
-
当向push_back()
:vector
容器使用push_back()
添加元素时,它首先需要一个已经存在的对象作为参数。如果传递的是临时对象或者右值引用,则会尝试通过移动构造函数来避免不必要的复制。-
std::vector<int> vec; vec.push_back(5); // 创建一个临时int对象并移动到vec末尾 std::string s = "hello"; vec.push_back(s); // 对于非内置类型,可能涉及到拷贝构造或移动构造
- 如果传入的是左值引用或者已经存在堆上的对象,将会调用相应的复制构造函数将该对象复制到
vector
的内部存储空间。
-
-
emplace_back()
:(1)emplace_back()
是在容器内直接就地构造元素的新实例,它通常接受与容器元素类型构造函数匹配的参数列表,并且不涉及临时对象的创建。-
std::vector<std::pair<int, std::string>> vec; vec.emplace_back(10, "world"); // 直接在vec内构建一个新的std::pair实例
- 由于省去了创建临时对象的过程,以及潜在的拷贝或移动操作,
emplace_back()
在某些情况下可以提供更高的性能和更低的资源消耗。 - 使用
emplace_back()
时,如果容器需要扩容,同样会进行内存分配和元素迁移的操作,但新元素是直接在新分配的空间上构造出来的。
-
-
-
任意位置插入:
vec.insert(vec.begin() + 2, 7); // 在索引2的位置插入元素7
访问元素
-
通过下标访问:
int value = vec[0]; // 访问第一个元素
-
迭代器访问:
for (std::vector<int>::iterator it = vec.begin(); it != vec.end(); ++it) { std::cout << *it << " "; }
或使用 C++11 及以后版本的范围基础 for 循环:
for (int element : vec) { std::cout << element << " "; }
删除元素
-
删除尾部元素:
vec.pop_back(); // 删除最后一个元素
-
删除特定元素或范围:
vec.erase(vec.begin() + 1, vec.begin() + 3); // 删除第二个到第三个元素(不包括第三个)
大小和容量操作
-
获取元素数量:
size_t size = vec.size();
-
检查是否为空:
bool isEmpty = vec.empty();
-
获取最大可能容量:
size_t maxSize = vec.max_size();
-
更改容器大小:
vec.resize(newSize); // 改变向量大小,可能增加或减少元素(新元素会默认初始化)
-
预留存储空间:
vec.reserve(capacity); // 预先分配存储空间,但不会改变元素数量
其他常用操作
-
清除所有元素:
vec.clear();
-
拷贝、赋值和移动:
std::vector<int> vecCopy(vec); // 深拷贝 std::vector<int> vec2; vec2 = vec; // 赋值操作,执行深拷贝 // C++11及以后的移动语义: std::vector<int> vecMoved(std::move(vec)); // 移动构造函数 vec = std::vector<int>(/*...*/); // 移动赋值
-
排序:
std::sort(vec.begin(), vec.end()); // 对向量内的元素进行排序
-
查找元素:
auto it = std::find(vec.begin(), vec.end(), value); if (it != vec.end()) { // 找到了value } else { // 没有找到value }