C++——STL标准模板库——容器详解——vector

发布时间:2023年12月18日

一、概念和特性

1、vector:可变大小数组的序列容器——动态数组。

2、vector像数组一样使用连续的空间储存元素,也可以通过下标访问元素。和数组不同的是,当vector容器中空间不足,vector会自动增大储存空间。

3、vector自增空间的原理是,先申请一块更大的储存空间,再将原空间中的数据拷贝到新空间,释放原空间。

4、当vector自增时,因为储存空间的地址已经改变,所以原来的迭代器也失效,需要重新获取。

5、vector不会在插入每个元素时进行自增,重新申请采用对数增长的空间大小,以至于使用尾插法添加元素时为常数时间的复杂度。

6、vector使用尾插法和尾删法增删元素,但其他元素的插入删除时间复杂度较其他序列容器更大大。

7、vector容器中有三个原始迭代器:start——指向储存空间的起始位置,也就是第一个元素;finish——指向已使用空间的末尾位置;end_of_storage——指向已分配储存空间的末尾位置。使用过程中申请的迭代器都是通过这三个原始迭代器获得的。

二、构造函数

vector构造函数有四种。

vector<T> v;? ? ? ? //默认构造函数,定义一个储存T类型元素的向量v

vector<T> v(n);? ? ? //定义一个储存了n个T类型元素的向量v,默认值为0

vector<T> v(n,value);//定义一个储存了n个T类型元素的向量v,并将所有元素初始化为value

vector<T> v(v1.begin(),v1.end());? ? ? ? //定义一个能够储存T类型元素的向量,将v1中begin()和end()区间内的元素拷贝到v中。

vector<T> v(v1);? ? ?//拷贝构造函数,定义一个容器v将v1中元素拷贝到v中。

#include<iostream>
using namespace std;
#include<vector>
#include<algorithm>

void myprint(const int value) {
	cout << value << " ";
}

void test() {
	/*构造函数1,默认构造函数*/
	vector<int> v1;
		//尾插法存储数据
	for (int i = 0; i < 10; i+=2) {
		v1.push_back(i + 1);
	}
		//利用vector容器的数组特性遍历数据
	for (int i = 0; i < (int)v1.size(); i++) {
		cout << v1[i] << " ";
	}
	cout << endl;

	/*构造函数2,能够储存10个T类型元素,元素默认值为0*/
	vector<int> v2(10);
		//利用迭代器给元素赋值
	int value = 2;
	for (vector<int>::iterator it = v2.begin(); it != v2.end(); it++) {
		*it = (value += 2);
	}
	for (int i = 0; i < (int)v2.size(); i++) {
		cout << v2[i] << " ";
	}
	cout << endl;

	/*构造函数3,能够储存10个T类型元素,并全部初始化成5*/
	vector<int> v3(10,5);
		//利用迭代器遍历数据
	for (vector<int>::iterator it = v3.begin(); it != v3.end(); it++) {
		cout << *it << " ";
	}
	cout << endl;

	/*构造函数4,申请一个容器v4,将v3中从begin(开)到end(闭)之间的数据拷贝到v4,*/
	vector<int> v4(v3.begin(), v3.end());
		//利用STL封装好的算法遍历数据,该函数返回回调函数的返回类型
	for_each(v4.begin(), v4.end(),myprint);
}
int main() {
	test();
	return 0;
}

三、增加函数

void vector<T>::push_back(const T& value);? ? ? ? //向量尾部添加一个元素

terator vector<T>::insert(iterator it,const T& value);?//向量中迭代器it指向位置的前面插入数据value

iterator vector<T>::insert(iterator it,int cnt,const T& value);? //向量中迭代器it指向位置的前面插入n个value

iterator vector<T>::insert(iterator it,iterator first,iterator last);//向量中插入同类型容器的一段数据,前闭后开?

insert函数返回指向原来位置的迭代器,原迭代器失效。

四、删除函数

iterator vector<T>::erase(iterator it);? ? ? ? //删除迭代器it指向的元素,返回指向该位置的新迭代器

iterator vector<T>::erase(iterator first,iterator lase);? //删除迭代器[first,last)之间的数据,前闭后开

void vector<T>::pop_back();? ? ? ? ? ? ? ? ? ?//删除向量尾部一个数据

void vector<T>::clear();? ? ? ? ? ? ? ? ? ? ? ? ? ?//清空向量

五、遍历函数

T& vector<T>::at(int index);? ? ? ? ? ? ? ? //返回下标index位置的数据的引用

T& [int index];? ? ? ? ? ? ? ? ? ?//向量的数组特性,[]运算符配合下标访问数据,返回该位置元素的引用

T& vector<T>::front();? ? ? ? ? ? ? ? ? ? ? ? //返回向量第一个元素的引用

T& vector<T>::back();? ? ? ? ? ? ? ? ? ? ? ? //返回向量最后一个元素的引用

iterator vector<T>::begin();? ? ? ? ? ? ? ? //返回指向第一个元素的迭代器

iterator vector<T>::end();? ? ? ? ? ? ? ? ? ?//返回指向最后一个元素后面位置的迭代器

reverse_iterator vector<T>::rbegin(); //反向迭代器,指向最后一个元素

reverse_iterator vector<T>::rend();? ? //反向迭代器,指向第一个元素前面一个位置

六、容量函数

bool vector<T>::empty() const;? ? ? ? ? //判断向量是否为空

int vector<T>::size() const;? ? ? ? ? ? ? ? //取向量中元素个数

int vector<T>::capacity() const;? ? ? ? ?//取当前向量的总容量

int vector<T>::max_size() const;? ? ? ?//取该向量允许的最大容量

void vector<T>::reserve(size_t newsize)//预留空间函数,当newsize小于原来向量容量无效。

七、其他函数

void vector<T>::assign(int n,const T& value);? ? ? ? //将n个value赋值给向量

void vector<T>::assign(iterator first,iterator last);//将[fist,last)之间的元素赋值给向量

void vector<T>::assign(initializer_list<T> _list);? ? ?//将列表list中的数据赋值给向量??

void vector<T>::swap(vector<T>);? ? ? ? ? ? ? ? ? ? ? ?//交换两个向量所有内容

八、基本用法

1、vector容器不仅能够储存内置数据类型:int、double、char等,还能存储类对象或者结构体。

class Person {
public:
	Person(string name, int age) :m_Name(name), m_Age(age) {}
	string m_Name;
	int m_Age;
};
typedef struct rect {
	int m_id;
	int m_length;
	int m_width;
	struct rect(int id, int length, int width) :m_id(id), m_length(length), m_width(width) {}
}Rect;
void test() {
	vector<Person> v;
	v.push_back(Person("张三", 20));
	vector<Rect> v1;
	v1.push_back(Rect(1, 10, 5));

	cout << v[0].m_Name << " " << v[0].m_Age << endl;
	cout << v1[0].m_id << " " << v1[0].m_length << " " << v1[0].m_width << endl;
}

2、vector可以储存任意数据类型的vector容器

void myprint(vector<int>& v) {
	for (vector<int>::iterator it = v.begin(); it != v.end(); it++) {
		cout << *it;
		if (it + 1 != v.end()) {
			cout << " ";
		}
		else {
			cout << endl;
		}
	}
}

void test() {
	vector< vector<int> >v;
	vector<int>v1,v2,v3;

	for (int i = 0; i < 5; i++) {
		v1.push_back(i);
		v2.push_back(i + 2);
		v3.push_back(i + 4);
	}

	v.push_back(v1);
	v.push_back(v2);
	v.push_back(v3);
	
	for_each(v.begin(), v.end(), myprint);
}

九、注意事项

1、vector容量(capacity)和大小(size)的区别

vector实例化对象时capacity可预先设定,当vector自增时需将原空间中数据赋值到新内存空间,为了避免数据量过大或者频繁发生数据拷贝影响效率,在使用时可申请足够大小容量(capacity)。

vector大小(size)是存储数据的个数,随着插入数据递增,删除数据递减。

2、vector容量(capacity)不会自减

vector的clear()函数清空向量中的数据,是将size设置为0。容量也就是向量所占内存空间并未改变。当需要释放向量所占空间时可以使用swap()函数与一个临时对象进行交换,利用临时对象参与运算后立即销毁的特性释放空间;或者插入一个大括号代码段进行交换,出大括号时自动析构交换过的向量。

void test() {
	vector<int>v(10);
	cout << v.size() << " " << v.capacity() << endl;
	v.clear();
	cout << v.size() << " " << v.capacity() << endl;
    //方法1
    vector<int>().swap(v);
    //方法2
	{
		vector<int>temp;
		v.swap(temp);
	}
	cout << v.size() << " " << v.capacity() << endl;
}

3、vector容器插入数据是插入对象的复制体,而不是插入对象本身,这种机制防止对象的操作影响向量内数据

void test() {
	vector< vector<int> >v;
	vector<int>v1,v2,v3;

	v.push_back(v1);
	v.push_back(v2);
	v.push_back(v3);
	
	for (int i = 0; i < 5; i++) {
		v1.push_back(i);
		v2.push_back(i + 2);
		v3.push_back(i + 4);
	}

	for_each(v.begin(), v.end(), myprint);
}

这个函数输出结果为空,验证了对象操作无法影响到向量内部数据

文章来源:https://blog.csdn.net/qq_42106610/article/details/134719929
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。