vector容器

今天,我们来讲解一下c++中的vector容器,它封装了动态大小数组的顺序容器,就相当于它能够存放各种类型的对象。可以简单的认为,vector是一个能够存放任意类型的动态数组

vector容器的特性

为了更好叙述下面的内容,我在这里先新建一个vector容器

生成一个vector容器

容器名 <容器存储对象的类型> 储存对象的名字
vector<int> tp;

顺序序列

vector容器中的元素按照严格的线性顺序排序。可以通过元素在序列中的位置访问对应的元素

对vector容器的第6位元素的值进行修改(类似于数组的修改)
tp[5] = 10;

动态数组

支持对序列中的任意元素进行快速直接访问,甚至可以通过指针算述进行该操作。提供了在序列末尾相对快速地添加/删除元素的操作

对vector容器的尾部进行插入操作
tp.push_back();
对vector容器的尾部进行删除操作
tp.pop_back();

能够感知内存分配器

容器使用一个内存分配器对象来动态地处理它的存储需求

vector容器的使用

我们在知道vector容器的基本用法后,我们是不是应该了解vector容器的用法了? ((^_^))

下面我们就从vector容器的构造开始讲起吧

容器构造

默认构造,不含参数的构造

vector<int> a;
//先构造再赋值
int i;
for (i = 0; i < 10; i++)
{
	a.push_back(i);
}

区间构造,把别人的复制到自己这里

vector<int> b(a.begin(), a.end());

n个elem的形式构造,往里面输入10个100进去

vector<int> c(n, elem);
vector<int> c(10, 100);

直接拷贝构造

vector<int> d(c);

容器赋值

采用for循环进行赋值

vector<int> a;
for (int i = 0; i < 10; i++)
{
	a.push_back(i);
}

采用了等号的方式直接赋值

vector<int>b;
	b = a;

采用类似于string容器中的assign操作

vector<int>c;
c.assign(a.begin(), a.end());

n个elem的形式构造,往里面输入10个100进去

vector<int>d;
d.assign(10, 100);

容器空间大小

初始化

vector<int> a;
for (int i = 0; i < 10; i++) {
	a.push_back(i);
}

判断容器是否非空,空的话返回0,反之返回1

a.empty();

改变容器内存空间

改变a的内存空间为15,size往后的多余部分以100补上

//假设一开始容器的初始空间大小是10,里面的值都是1
//改变容器的大小为n,如果一开始容器的大小不足n,后面的值全部赋以elem,如果一开始容器的大小大于或等于n,只是对容器的大小进行了缩水
a.resize(n, elem);

改变a的内存空间为16,size往后的多余部分以默认值0补上

//elem不写默认是0
a.resize(n,elem);
a.resize(16);

改变a的内存空间为5,减少空间,在5个空间内的值不变,其它值全部删去

a.resize(5);

容器的插入和删除

vector<int> a;
	int i;
	for (i = 0; i < 10; i++)
	{
        //对a容器尾部添加数值
		a.push_back(i);
	}

对a尾部的数值进行删除

a.pop_back();

头插法,对a头部插入一个指定的值100

//对a的头部插入n个数值为elem的数,n不写默认为1
a.insert(a.begin(),n,elem);
a.insert(a.begin(), 100);
a.insert(a.begin(), 2, 1000);

头删法,对a头部进行删除

a.erase(a.begin());

选择删除法,对a整个容器进行删除

a.erase(a.begin(),a.end());

删除a容器里面的所有数值

a.clear();

判断容器是否非空

a.empty();

容器内数据读取

初始化

vector<int> a;
int i;
for (i = 0; i < 10; i++)
{
	a.push_back(i);
}

按照顺序输出a容器

//数组方式
for (i = 0; i < a.size(); i++)
{
	cout << a[i] << ' ';
}
cout << endl;
//访问底层数据方式
for (i = 0; i < a.size(); i++)
{
	cout << a.at(i) << ' ';
}
cout << endl;

容器互换

初始化

vector<int> a,b;
int i;
for (i = 0; i < 10; i++)
{
	a.push_back(i);
}
for (i = 10; i >=0; i--)
{
	b.push_back(i);
}

两个容器互换

a.swap(b);

容器互换的意义

void test7()
{
	vector<int> a;
    
	for (int i = 0; i < 100000; i++)
	{
		a.push_back(i);
	}
    
    //容量过大无法压缩容量
	cout << "a.capacity()= " << a.capacity() << endl;
	cout << "a.size()= " << a.size() << endl;
    
	//重定义大小改不了容量
	a.resize(3);
	cout << "a.capacity()= " << a.capacity() << endl;
	cout << "a.size()= " << a.size() << endl;
    
	//自己给自己交换,将容量重定义为3了
	vector<int>(a).swap(a);
	cout << "a.capacity()= " << a.capacity() << endl;
	cout << "a.size()= " << a.size() << endl;
    
}

容器内数据的输出

void printvector(vector<int>& a)
{
	for (vector<int>::iterator it = a.begin(); it != a.end(); it++)
	{
		cout << *it << ' ';
	}
	cout << endl;
}

容器的预留空间

void test8()
{
	vector<int> a;
	int num = 0;
	//开始的时候初始化指针p为空指针
	int* p = NULL;
	for (int i = 0; i < 10000; i++)
	{
		a.push_back(i);
		//如果要往a容器插数,就要开辟内存,如果一段内存不够用的话,就会新开一段大内存,
		//释放原来的内存,此时指针的地址变化就说明了内存在扩大,地址变化
		if (p != &a[0])
		{
			p = &a[0];
			num++;
		}
	}
	cout << "num= " << num << endl;
}
//vector 的减少预留空间扩张的方法,事先判断可能会开多大,采用reserve函数预处理开辟的内存空间
void test9()
{
	vector<int> a;
	a.reserve(10000);
	int num = 0;
	//开始的时候初始化指针p为空指针
	int* p = NULL;
	for (int i = 0; i < 10000; i++)
	{
		a.push_back(i);
		//如果要往a容器插数,就要开辟内存,如果一段内存不够用的话,就会新开一段大内存,
		if (p != &a[0])
		{
			//释放原来的内存,此时指针的地址变化就说明了内存在扩大,地址变化
			p = &a[0];
			num++;
		}
	}
    //此时的num就只为1,就是第一次开辟的10000的空间,之后都没有开辟新的空间
	cout << "num= " << num << endl;
}