什么是vector
在 C++ 标准模板库(STL)中,
vector
是一种序列容器,表示可以改变大小的数组。它是通过模板实现的,因此可以用于存储任何类型的对象,只要这些对象支持拷贝构造函数和析构函数
vector的特点
- 动态数组:
vector
在内部使用一个动态分配的数组来存储元素。当数组满时,vector
会自动重新分配更大的内存空间,并将现有元素复制到新的内存位置。- 连续存储:
vector
保证所有元素都存储在连续的内存位置中,这使得通过索引访问元素非常高效。- 随机访问:由于元素是连续存储的,
vector
支持快速随机访问,时间复杂度为 O(1)。- 动态大小:
vector
可以在运行时动态地增加或减少其大小,这是通过push_back
、pop_back
、insert
和erase
等成员函数实现的。- 自动内存管理:
vector
管理自己的内存,当vector
被销毁或其大小被减少时,它会自动释放不再需要的内存
vector常用的函数接口
1)构造函数
①默认构造函数,创造一个空的vector容器
vector();
②构造一个vector类对象并用n个val初始化
vector(size_t n, const value_type& val);
创建一个包含 n
个元素的 vector
,并且所有元素都是初始值 val
使用
注:value_type
是 vector
存储元素的类型
③拷贝构造函数
vector(const vector& other);
创建一个新 vector
作为另一个已存在 vector
的副本使用
④使用迭代器进行初始化构造
template <class InputIterator> vector(InputIterator first, InputIterator last);
使用迭代器指定的范围来初始化 vector
时使用,这个范围包括 [first, last)
中的元素
注:InputIterator
是一种迭代器类型,它可以是任何能够用于迭代的类型,比如指针或者其它容器的迭代器
2)容量操作
①size
size_t size() const;
获取vector中元素个数
②capacity
size_t capacity() const;
获取vector当前容量( vector
在不重新分配内存的情况下可以容纳的最大元素数量)
③empty
bool empty() const;
检查vector是否为空
④resize
void resize(size_t n, value_type val = value_type());
改变vector的大小,多出来的会填充默认值
用来调整 vector
的大小到 n
个元素。
①如果 n
小于当前大小,则删除多余的元素;
②如果 n
大于当前大小,则添加新元素,并用 val
初始化它们
⑤reverse
void reserve(size_t n);
设置vector的容量
用来预留至少能够容纳 n
个元素的内存空间。这不会改变 vector
的 size,但会增加其 capacity
3)访问和遍历
①operator[]
reference operator[](size_t n); const_reference operator[](size_t n) const;
访问vector中的元素
通过索引 n
访问 vector
中的元素。不检查索引是否有效,因此使用时需确保索引在有效范围内
注:reference
和 const_reference
分别表示对 vector
元素的引用和常量引用
②迭代器(正向和反向迭代器)
iterator begin(); const_iterator begin() const; iterator end(); const_iterator end() const; reverse_iterator rbegin(); const_reverse_iterator rbegin() const; reverse_iterator rend(); const_reverse_iterator rend() const;
遍历vector中的元素
③at
reference at(size_type n); const_reference at(size_type n) const;
访问vector中的元素,并提供边界检查
通过索引 n
安全地访问 vector
中的元素。如果索引无效,则抛出 std::out_of_range
异常
④front and back
reference front(); const_reference front() const; reference back(); const_reference back() const;
front -- 访问vector的第一个元素
back -- 访问vector的最后一个元素
[如vector为空,则行为未定义]
4)vector的增删查改
①push_back
void push_back(const value_type& val);
在vector的末尾添加一个元素,如果需要,会自动增加 vector
的容量
②pop_back
void pop_back();
删除vector末尾的元素
③find
template <typename InputIterator, typename T> InputIterator find(InputIterator first, InputIterator last, const T& val);
find查找两个迭代器区间的val值
find不是vector的成员函数
④insert
iterator insert(const_iterator position, const value_type& val); iterator insert(const_iterator position, size_type n, const value_type& val); template <class InputIterator> iterator insert(const_iterator position, InputIterator first, InputIterator last);
在迭代器 插入1个 或多个元素 或一个vector类对象
⑤erase
iterator erase(const_iterator position); iterator erase(const_iterator first, const_iterator last);
⑥swap
void assign(size_type n, const value_type& val); template <class InputIterator> void assign(InputIterator first, InputIterator last);
⑦assign
void assign(size_type n, const value_type& val); template <class InputIterator> void assign(InputIterator first, InputIterator last);
为vector指定新内容
⑧clear
void clear() noexcept;
清空,size为0
什么是迭代器失效
迭代器的失效是指由于容器的修改操作,使得原有迭代器不再有效,无法正确访问容器元素
简单来说:
迭代器失效就像是你拿着指向某个物品的指针,但物品的位置变了,你的指针就找不到原来的物品了
通常发生在以下几种情况:
- 容器内存重新分配:当容器如 vector 或 string 因为增加元素而需要重新分配内存时,之前指向容器元素的迭代器、指针和引用会失效。
- 容器元素删除:当通过 erase、clear 或 pop_back 等操作从容器中删除元素时,指向被删除元素或被删除元素之后元素的迭代器会失效。
- 容器插入操作:在序列容器(如 vector、deque、string)中插入元素可能会使插入点之后的所有迭代器失效
如何避免迭代器失效
专业术语:
1、重获迭代器:在容器修改操作后,使用返回的有效迭代器更新现有迭代器。
2、范围删除:使用基于范围的 erase 方法来删除元素,避免单独删除导致的迭代器失效。
3、避免失效操作:了解哪些容器操作会导致迭代器失效,并尽量规避。
简单来讲:
更新指针:当你删除或添加元素后,记得重新获取新的迭代器位置。
一次性清理:如果需要删除多个元素,尽量一次性完成,而不是一个一个删。
别用坏指针:知道哪些操作会让迭代器变坏,就不要在那些操作后继续使用旧的迭代器。
总结
避免迭代器失效的关键在于:
操作后更新迭代器,批量处理元素,以及避免使用已失效的迭代器