C++头文件容器库——vector
vector的使用,首先添加头文件 vector 是封装动态数组的顺序容器。元素相继存储,不仅可通过迭代器,还能用指向元素的常规指针访问元素。vector 的存储是自动管理的,按需扩张收缩; vector 通常占用多于静态数组的空间,因为要分配更多内存以管理将来的增长; vector 所用的方式不在每次插入元素时,而只在额外内存耗尽时重分配。函数接口(c++20):函数作用:将 other 中的
vector的使用,首先添加头文件 #include <vector>
vector 是封装动态数组的顺序容器。元素相继存储,不仅可通过迭代器,还能用指向元素的常规指针访问元素。vector 的存储是自动管理的,按需扩张收缩; vector 通常占用多于静态数组的空间,因为要分配更多内存以管理将来的增长; vector 所用的方式不在每次插入元素时,而只在额外内存耗尽时重分配。
1. 赋值函数
1.1 操作(operator) “=”
函数接口(c++20):
constexpr vector& operator=( const vector& other );
函数作用:将 other 中的 vector 赋值给 “=” 之前的 vector;不是地址引用,是赋值重建;
常规使用示例:
vector<int>& nums1 = {3, 1, 4, 6, 5, 9};
vector<int>& nums2;
nums2 = nums1; //nums2 = {3, 1, 4, 6, 5, 9};
// 移动赋值
vector<int>& nums3;
nums3 = move(nums1); //nums3 = {3, 1, 4, 6, 5, 9}; nums1={}
1.2 assign(将值赋给容器)
函数接口(c++20):
1.2.1 以 count 份 value 的副本替换内容。
constexpr void assign( size_type count, const T& value );
参数含义:
- count - 容器的新大小;
- value - 用以初始化容器元素的值 ;
常规使用示例:
vector<char> characters;
characters.assign(5, 'a'); //characters={'a','a','a','a','a'}
1.2.2 以范围 [first, last) 中元素的副本替换内容。
constexpr void assign( InputIt first, InputIt last );
参数含义: first, last - 复制来源元素的范围
说明:若 InputIt 为整数类型,则此重载与1.2.1拥有相同效果。
常规使用示例:
vector<char> characters;
characters.assign({'C', '+', '+', '1', '1'}); // characters = “C++11”
1.3 vector的初始化
1.3.1 默认初始化
vector<int> test1; //构造一个空的vector容器
vector<int> test(7); //test={0,0,0,0,0,0},构造大小为7,其中值为0的vector容器
vector<int> list(7,3); //list={3,3,3,3,3,3,3}
1.3.2 赋值构造
vector<int> list = {1,2,3,4,5,6,7};
vector<int> list{1,2,3,4,5,6,7};
vector<int> list;
list.assign(7,3); //list={3,3,3,3,3,3,3}
1.3.3 通过数组构造
int a[] ={1,2,3,4,5};
vector<int>list(a,a+5);
// (a,a+5)的含义为:a[0]-a[4];
//list3={1,2,3,4,5};
1.3.4 拷贝构造
vector<int> list1 = {1,2,3,4,5,6,7};
vector<int> list2(list1); //list2 = {1,2,3,4,5,6,7};
等价于
vector<int> list2 = list1;
vector<int> list3(list1.begin()+2, list1.end()-1); // list3={3,4,5,6}
2. 访问函数
2.1 访问指定元素
vector<int> data = { 1, 2, 4, 5, 7, 6 };
data[0]; // 1
data[4]; // 7
2.1.1 at —— 访问指定的元素,同时进行越界检查
函数接口(c++20):
constexpr reference at( size_type pos );
参数含义:pos - 要返回的元素的位置 ;
函数作用:
- 返回位于指定位置 pos 的元素的引用,有边界检查;
- 若 pos 不在容器范围内,则抛出 out_of_range 类型的异常;
- 返回到所需元素的引用。
常规使用示例:
vector<int> data = { 1, 2, 4, 5, 5, 6 };
data.at(1) = 88;
data.at(6) = 666; //索引 pos超限,报错
// data = { 1, 88, 4, 5, 5, 6 };
2.2.2 访问首尾元素
vector<int> data = { 1, 2, 4, 5, 5, 6 };
1.首元素
data.front(); // 1
2. 尾元素
data.back(); // 6
3. 迭代器
3.1 正向迭代器
函数接口
1. 返回指向 vector 首元素的迭代器:
constexpr iterator begin() noexcept; // 注意:若 vector 为空,则返回的迭代器将等于 end();
2. 返回指向 vector 末元素后一元素的迭代器:
constexpr iterator end() noexcept;
使用案例:
vector<int> nums;
sort(nums.begin(), nums.end());
3.2 逆向迭代器
函数接口
1.返回指向第一个元素之前一个位置的反向迭代器。
constexpr const_reverse_iterator rend() const noexcept;
2.返回指向最后一个元素的反向迭代器;
constexpr const_reverse_iterator rbegin() const noexcept;
使用案例:
vector<int>values{1,2,3,4,5};
auto first = values.rbegin();
auto end = values.rend();
while (first != end)
{
cout << *first << " ";
++first;
}
// 5 4 3 2 1
4. 容量大小操作
4.1 检测是否为空
若容器为空则返回 true ,否则返回 false
vector<int>values1{1,2,3,4,5};
vector<int>values2;
bool label1 = values1.empty(); // false
bool label2 = values1.empty(); // true
4.2 元素数量
vector<int>values1{1,2,3,4,5};
int n = values1.size(); // 5
4.3 改变容器中可存储元素的个数
函数接口(c++20):
1.重设容器大小以容纳 count 个元素,后附额外的默认插入的元素
constexpr void resize( size_type count );
2.重设容器大小以容纳 count 个元素,后附额外的 value 的副本元素
constexpr void resize( size_type count, const value_type& value );
注意:若当前大小大于 count ,则减小容器为前 count 个元素。
常规使用示例:
vector<int> c = {1, 2, 3};
c.resize(5); // 1,2,3,0,0
c.resize(7,6); // 1,2,3,0,0,6,6
c.resize(2); // 1,2
4.4 存储空间
4.4.1 预留存储空间
函数接口(c++20):
constexpr void reserve( size_type new_cap ); // new_cap - vector 的新容量
作用:
- 增加 vector 的容量达到 new_cap;
- 若 new_cap 大于当前的 capacity() ,则分配新存储,否则该方法不做任何事;
- reserve() 不更改 vector 的 size;
- 若 new_cap 大于 capacity() ,则所有迭代器,包含尾后迭代器和所有到元素的引用都被非法化。否则,没有迭代器或引用被非法化。
使用案例:
vector<int>values(7); // values的容量为 7
values.reverse(100); // values的容量为 100
4.4.2 返回当前存储空间能够容纳的元素数
函数接口(c++20):
constexpr size_type capacity() const noexcept;
使用案例:
vector<int>values1;
vector<int>values2(7);
values1.
int num = values1.capacity(); // 0
int num = values2.capacity(); // 7
4.4.3 释放未使用的内存
函数接口(c++20):
constexpr void shrink_to_fit();
作用:
- 请求移除未使用的容量;
- 它是减少 capacity() 到 size()非强制性请求,请求是否达成依赖于实现;
- 若发生重分配,则所有迭代器,包含尾后迭代器,和所有到元素的引用都被非法化。若不发生重分配,则没有迭代器或引用被非法化。
使用案例:
vector<int> list;
list.capacity(); // 0
list.resize(100);
list.capacity(); // 100
list.resize(50);
list.capacity(); // 100
list.shrink_to_fit();
list.capacity(); // 50
5. 内容修改
5.1 清除元素
5.1.1 清除全部元素
函数接口(c++20):
constexpr void clear() noexcept;
作用:
- 从容器擦除所有元素,此调用后 size() 返回零;
- 非法化任何指代所含元素的引用、指针或迭代器。任何尾后迭代器亦被非法化;
- 保持 vector 的 capacity() 不变。
使用案例:
vector<int>values{1,2,3,4,5};
values.size(); // 5
values.clear(); //values={}
values.size(); // 0
values.capacity(); // 5
5.1.2 擦除元素
函数接口(c++20):
1.移除位于 pos 的元素
constexpr iterator erase( const_iterator pos );
2.移除范围 [first; last) 中的元素
constexpr iterator erase( const_iterator first, const_iterator last );
注意:
- 能以 end() 迭代器为 pos 的值;
- 擦除空范围是无操作
返回值:最后移除元素的迭代器。
- 若 pos 指代末元素,则返回 end() 迭代器;
- 若在移除前 last == end() ,则返回更新的 end() 迭代器;
- 若 [first, last) 为空范围,则返回 last
使用案例:
vector<int> c{0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
c.erase(c.begin()); // 1, 2, 3, 4, 5, 6, 7, 8, 9
c.erase(c.begin()+2, c.begin()+5); // 1, 2, 6, 7, 8, 9
5.1.3 移除末尾元素
函数接口(c++20):
constexpr void pop_back(); //移除容器的末元素。
使用案例:
vector<int> c{6, 7, 8, 9};
c.pop_back(); // 6,7,8
5.2 构造元素
5.2.1 插入元素
函数接口(c++20):
1.在 pos 前插入 value
constexpr iterator insert( const_iterator pos, const T& value );
2.在 pos 前插入 count 个 value
constexpr iterator insert( const_iterator pos, size_type count, const T& value );
3.在 pos 前插入 InputIt的[first,last)元素
constexpr iterator insert( const_iterator pos, InputIt first, InputIt last );
4.在 pos 前插入 ilist 的元素
constexpr iterator insert( const_iterator pos, std::initializer_list<T> ilist );
参数含义:
- pos - 将内容插入到其前的迭代器。 pos 可为 end() 迭代器;
- value - 要插入的元素值;
- count - 要插入的元素数量;
- first, last - 要插入的元素范围,不能是指向调用 insert 所用的容器中的迭代器 ;
- ilist - 要插入的值来源的list ;
指向被插入 value 的迭代器。
常规使用示例:
vector<int> vec(3,100); // 100,100,100
vec.insert(vec.begin(), 200); // 200,100,100,100
vec.insert(vec.begin(),2,300); // 300,300,200,100,100,100
vector<int> vec2(2,400);
auto it = vec.begin();
vec.insert(it+1, vec2.begin(), vec2.end()); // 300,400,400,300,200,100,100,100
int arr[] = { 501,502,503 };
vec.insert(vec.begin(), arr, arr+3); // 501,502,503,300,400,400,300,200,100,100,100
5.2.2 原位构造元素
函数接口(c++20):
直接在 pos 前插入元素,返回指向被安置的元素的迭代器。
constexpr iterator emplace( const_iterator pos, Args&&... args );
// 其中,pos为构造新元素到其前的迭代器
注意:若新的 size() 大于 capacity() ,则所有迭代器和引用都被非法化。否则,仅在插入点前的迭代器和引用保持合法。尾后迭代器亦被非法化。
使用案例 :
vector<int> myvector = {10,20,30};
auto it = myvector.emplace ( myvector.begin()+1, 100 ); // 10,100,20,30
myvector.emplace ( it, 200 ); // 10,200,100,20,30
myvector.emplace ( myvector.end(), 300 ); // 10,200,100,20,30,300
5.2.3 将元素添加到容器末尾
函数接口(c++20):
constexpr void push_back( const T& value );
使用案例:
vector<int> myvector = {10,20,30};
myvector.push_back(50); // 10,20,30,50
5.2.4 在容器末尾就地构造元素
函数接口(c++20):
constexpr reference emplace_back( Args&&... args );
使用案例:
vector<int> myvector = {10,20,30};
myvector.emplace_back(50); // 10,20,30,50
5.3 区别
5.3.1 insert
和 emplace
的区别
insert是插入一个完全的对象,而emplace是先调用该对象的构造函数生成的对象,再把这个对象插入vector中。
使用emplace时,该对象类必须有相应的构造函数;
emplace 最大的作用是避免产生不必要的临时变量。
5.3.2 push_back
和 emplace_back
的区别
push_back()方法要调用构造函数和复制构造函数,这也就代表着要先构造一个临时对象,然后把临时的copy构造函数拷贝或者移动到容器最后面;
emplace_back()则是直接在容器的尾部创建这个元素,省去了拷贝或移动元素的过程。
6. 两个vector 之间的内容交换
函数接口(c++20)
将内容与 other 的交换,不在单个元素上调用任何移动、复制或交换操作。
constexpr void swap( vector& other ) noexcept(/* see below */);
使用案例:
vector<int> a1{1, 2, 3};
vector<int> a2{4, 5};
a1.swap(a2);
// a1 = {4, 5};
// a2 = {1, 2, 3};
更多推荐
所有评论(0)