当前位置:   article > 正文

【C++ STL】Vector容器成员方法常用操作和使用场景(超详细)_c++ vector container

c++ vector container

在这里插入图片描述

vector 容器

一:基本概念和存储结构

(1)基本概念

STL vector 表示的是对象的集合,其中所有对象的类型都相同。集合中的每个对象都有一个与之对应的索引,索引用于访问对象。因为 vector“容纳着”其他对象,所以它也常被称作容器(container)。

vector 数据结构和数组非常相似,也称为单端数组,即只允许向数组的一头进行输入输出操作,符合前闭后开原则

注意:vector是模板而非类型,由vector生成的类型必须包含vector中元素的类型,例如vector。

(2)vector 跟普通数组的区别

数组是静态空间,而vector是可以动态扩展的,也可以叫做可变长数组

动态扩展并不是在原空间后续接空间,而是重新创建一个更大的新空间,复制到新空间上,然后释放原空间

(3)vector容器存储结构图

vector容器的基本迭代器

迭代器是一种用于访问容器元素的对象,类似于指针,可以通过迭代器来遍历容器中的元素。

这里可以加深对迭代器的了解:c++ STL 常用迭代器以及使用

二:对象成员函数使用

(1)打印 vector 对象

void printVector(vector<int>& v) {
	for (vector<int>::iterator it = v.begin(); it < v.end(); it++) {
		cout << *it << " ";
	}
	cout << endl;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

(2)定义和初始化vector对象

void test01(){
	//默认构造 无参构造 
	vector<int> v1;
	for (int i = 0; i < 10; i++)
	{
		v1.push_back(i);
	}
	cout << "v1 = ";
	printVector(v1);
	
	// 拷贝构造 
	vector<int> v2(v1);
	cout << "v2 = ";
	printVector(v2);
	
	// operator= 赋值  
	vector<int>v3;
	v3 = v1;
	cout << "v3 = ";
	printVector(v3);
	
	// assign 函数赋值
	vector<int>v4;
	v4.assign(10, 100);
	cout << "v4 = ";
	printVector(v4);
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27

关键概念:vector对象能高效增长:

C++标准要求 vector 应该能在运行时高效快速地添加元素。
既然 vector 对象能高效地增长,那么在定义 vector 对象的时候设定其大小也就没什么必要了,事实上如果这么做性能可能更差。只有一种例外情况,就是所有 (all) 元素的值都一样。一旦元素的值有所不同,更有效的办法是先定义一个空的 vector 对象,再在运行时向其中添加具体值。

开始的时候创建空的 vector 对象,在运行时再动态添加元素,这一做法与C语言及其他大多数语言中内置数组类型的用法不同。特别是如果用惯了C或者 Java,可以预计在创建vector 对象时顺便指定其容量是最好的。然而事实上,通常的情况是恰恰相反。`

(3)vector 对象容量和大小

void test02() {
	vector<int>v; //默认构造
	v.assign(10, 100);
	if (v.empty()) //判断是否为空
	{
		cout << "v为空" << endl;
	}
	else {
		cout << "v不为空" << endl;
	}
	cout << "v容量为:" << v.capacity() << endl; // 10
	cout << "v大小为:" << v.size() << endl;     // 10

	//resize()两种用法
	v.resize(3); // 指定容器数据大小为 size =  3
	cout << "v容量为:" << v.capacity() << endl; // 10 
	cout << "v大小为:" << v.size() << endl;     // 3

	v.resize(10, 100); //指定容器的大小为10,数据为100
	cout << "v容量为:" << v.capacity() << endl; // 10
	cout << "v大小为:" << v.size() << endl;     // 10
	printVector(v);
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23

(4)vector 插入和删除

函数原型:

// 在指定位置 pos 插入多个相同的元素,共插入 count 个,并使用给定的 value 初始化这些元素。返回一个指向第一个插入元素的迭代器。
iterator insert(const_iterator pos, size_type count, const T& value);
// 在指定位置 pos 插入一个元素,并使用给定的 value 初始化该元素。返回一个指向插入元素的迭代器。
iterator insert(const_iterator pos, const T& value);
// 从容器中删除位于指定位置 pos 的元素,并返回一个指向被删除元素后一个元素的迭代器。
iterator erase(const_iterator pos);
// 从容器中删除范围 [first, last) 内的所有元素,并返回一个指向被删除元素后一个元素的迭代器。
iterator erase(const_iterator first, const_iterator last);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

代码示例:

void test03(){
	vector<int>v;
	// 尾插
	v.push_back(10);
	v.push_back(1);
	v.push_back(6);
	v.push_back(4);
	printVector(v);

	// 尾删
	v.pop_back();
	printVector(v);

	// insert(pos,val) 插入操作
	v.insert(v.begin(), 2);
	printVector(v);
	
	// 批量插,begin()后插入2个元素10
	v.insert(v.begin(), 2, 10);
	printVector(v);

	// erase(pos)删除操作
	v.erase(v.begin());
	printVector(v);
	// erase(first,lasr)清空操作
	v.erase(v.begin(), v.end());
	printVector(v);
	// clear()清空操作
	v.clear();
	printVector(v);
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31

(5)vector 对象数据存取

函数原型:

//此函数返回指定位置 pos 处的元素的引用,并进行边界检查。如果 pos 超出了容器范围,会抛出 std::out_of_range 异常。
1. at(size_type pos); 
// 此操作符允许通过下标 pos 直接访问容器中的元素,与 at 类似,但不进行边界检查。如果 pos 超出了容器范围,会导致未定义行为。
2. operator[](size_type pos); 
// 此函数返回容器中第一个元素的引用。
3. front(); 
 // 函数返回容器中最后一个元素的引用。
4. back();
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

代码示例:

// 测试
void test04()
{
	vector<int>v;
	for (int i = 0; i < 10; i++) {
		v.push_back(i);
	}
	printVector(v);
	cout << v.at(1) << endl;
	cout << v[2] << endl;
	cout << v.front() << endl; // 头数据
	cout << v.back() << endl;  // 尾数据

}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

(6)vector 对象互换

swap() 实际用途:

//互换容器 swap() 以及实际用途
void test05()
{
	vector<int>v1;
	for (int i = 0; i < 10; i++)
	{
		v1.push_back(i);
	}
	printVector(v1);

	vector<int>v2;
	for (int i = 10; i > 0; i--)
	{
		v2.push_back(i);
	}
	printVector(v2);
	v1.swap(v2); //互换操作
	printVector(v1);
	printVector(v2);
	cout << "v1容量为:" << v1.capacity() << endl;
	cout << "v1大小为:" << v1.size() << endl;
	//v1容量为:13 //系统预留大小
	//v1大小为:10

	//实际用途 收缩多余的内存
	v1.resize(3);
	cout << "v1容量为:" << v1.capacity() << endl;
	cout << "v1大小为:" << v1.size() << endl;
	printVector(v1);
	//v1容量为:13
	//v1大小为:3

	//巧用swap来收缩内存
	vector<int>(v1).swap(v1);
	//vector<int>(v1)匿名对象,利用拷贝构造函数来创建一个新的对象,
	//匿名对象(无名)的容量,大小都是v1所用的个数大小,然后swap与原来v1进行互换(根据swap源码:相当于指针的交换)
	//执行完这行代码后,系统会将匿名对象回收(匿名对象的特点,当前行执行完,会被系统自动回收)
	cout << "v1容量为:" << v1.capacity() << endl;
	cout << "v1大小为:" << v1.size() << endl;
	printVector(v1);
	//v1容量为:3
	//v1大小为:3
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43

(7)vector 预留空间

函数原型:

// 调整字符串的长度,使其包含 count 个字符。如果 count 小于当前字符串的长度,则字符串将被截断;如果 count 大于当前字符串的长度,则字符串将被扩展,新的字符用空字符填充。
resize(size_type count); 
// 请求字符串的内存容量至少为 new_cap,但不保证实际的容量会达到 new_cap。
reserve(size_type new_cap);
  • 1
  • 2
  • 3
  • 4
resize() 和 reserve() 的区别:

(1)功能区别

resize()函数
用于调整容器的大小,可以增加或减少容器的元素数量。当增加容器的大小时,会在容器中添加新的元素,并进行默认初始化。当减少容器的大小时,会删除多余的元素。resize()可以用于改变容器的大小并实际操作元素。

reserve()函数
用于向容器预留一定的存储空间,以便在后续的操作中减少重新分配内存的次数。reserve()仅分配内存空间,但不改变容器的大小。它只是预留了一定的容量,可以用于减少动态扩展和内存分配的次数。

(2)参数区别

resize() 函数
接受一个参数,用于指定容器的目标大小。如果目标大小大于当前容器的大小,则会添加新的元素以扩展容器。如果目标大小小于当前容器的大小,则会删除多余的元素。

reserve() 函数
接受一个参数,用于指定预留的容量大小。这个参数表示容器预留的存储空间,不涉及容器中元素的个数。

(3)容器大小区别

resize() 函数
会实际改变容器的大小,因此容器的大小会与指定的目标大小相匹配。

reserve() 函数
仅预留容器的存储空间,容器的大小仍然是实际元素的个数。

(4)元素初始化区别

resize() 函数
在增加容器大小时,会对新添加的元素进行默认初始化。这意味着添加的元素将使用默认构造函数进行初始化。

reserve() 函数
仅预留容器的存储空间,不会初始化预留的空间。因此,在使用 reserve() 预留空间后,容器的元素仍然需要通过其他操作进行初始化

代码示例:

void test06(){
	vector<int>v;
	v.reserve(100000); // reserve()仅分配预留的内存空间大小,不改变容器的大小,也没有初始化的操作,可以减少动态扩展的次数
	//v.resize(100000); // resize() 函数在增加容器大小时,会对新添加的元素进行默认初始化。默认为0
	cout << "v的容量大小:" << v.capacity() << endl;
	cout << "v的数据大小:" << v.size() << endl;
	//cout << v[0] << endl; // 证明v.reserve()没有初始化v
	int num = 0;   //记录动态扩展的次数
	int* p = NULL; //记录vector的头地址

	for (int i = 0; i < 100000; i++)
	{
		v.push_back(i);
		if (p != &v[0]) { //检查地址是否变化
			p = &v[0];
			num++;
		}
	}
	cout << "动态扩展的次数:" << num << endl; // 次数为:1
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20

三:总结

以上就是vector容器的全部内容。

需要注意的是,虽然 vector 在尾部操作上非常高效,但如果需要在中间或开头进行大量的插入和删除操作,可能需要考虑其他数据结构,如 deque 或 list。


若有错误之处请指出,欢迎在评论区留言!记住多动手编程哦!
欢迎关注

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小舞很执着/article/detail/761466
推荐阅读