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 insertemplace 的区别

insert是插入一个完全的对象,而emplace是先调用该对象的构造函数生成的对象,再把这个对象插入vector中。

使用emplace时,该对象类必须有相应的构造函数;

emplace 最大的作用是避免产生不必要的临时变量。

5.3.2 push_backemplace_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};
Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐