C++ STL vector容器详解

1、vector VS array

  • vector被称为单端动态数组。
    在这里插入图片描述

  • vector的数据安排及操作方式与array非常相似,唯一差别在于空间运用的灵活性。

  • array是静态空间,一旦配置就不能改变,要更换空间必须手动配置一块新的空间,再将旧的数据搬到新空间,再释放原空间。

  • vector是动态空间,随着元素的加入,它的内部机制会自动扩充空间来容纳新元素。

  • vector的实现技术,关键在于对大小的控制及重新配置时数据移动效率。“配置新空间-移动数据-释放旧空间”时间成本很高,因此容器每次扩充并不是一个一个的扩充。

2、vector迭代器

  • vector维护一个线性空间,不论元素类型如何,普通指针都可以作为vector的迭代器,因为迭代器所需要的行为如operator->,operator++,operator–,operator+,operator-,operator+=,operator-=普通指针天生具有。
  • vector支持随机存取,而普通指针正有这样的能力。
  • vector提供的是随机访问迭代器(Random Access Iterator)。
    随机访问迭代器:迭代器+n可以通过编译就是随机访问迭代器。

3、vector空间容量

vector容量capacity和大小size的区别(capacity≥size):
capacity:空间能容纳元素最大个数。
size:空间中实际存放元素个数。

void test2()
{
	vector<int> v;
	for (int i = 0; i < 100; i++)
		v.push_back(i);
	cout << "capacity=" << v.capacity() << endl;
	cout << "size=" << v.size() << endl;
}

在这里插入图片描述

4、vector空间扩充

vector采用的数据结构非常简单,线性连续空间,它以两个迭代器Myfirst和Mylast指向配置得来的连续空间中已被使用的范围,以迭代器Myend指向整块连续内存空间的尾端。
为了降低空间配置时的速度成本,vector实际配置的大小可能比客户需求大一些,已备将来可能的扩充。即一个vector的容量永远大于或等于其大小,一旦容量等于大小,便是满载,下次再有新增元素,整个vector容器就会另寻空间。
所谓动态增加大小,并不是在原空间之后连续接新空间(因为无法保证原空间之后尚有可配置的空间,而判断当前开辟空间的后面空间是否已被占用是很耗时间的),因此每次都开辟一块更大的内存空间,然后将原数据拷贝新空间,并释放原空间。
因此对于vector的任何操作,一旦引起空间的重新配置,指向原vector的所有迭代器就都失效了。

void test3()
{
	vector<int> v;
	int* p = NULL;
	int count = 0;
	for (int i = 0; i < 20; i++)
	{
		v.push_back(i);
		if (p != &v[0])//当p与v的首地址不同时,就表明新开辟了一次空间
		{
			count++;
			p = &v[0];//原地址失效,这里获取新的起始地址			
		}
		cout << "count=" << count <<" capacity="<<v.capacity()<<" size="<<v.size()<< endl;
	}
	cout << "新开辟了" << count << "次空间" << endl;
}

在这里插入图片描述

5、vector函数接口

/************************构造函数*******************************/
vector<T> v;//采用模板类实现,默认构造函数
vector(v.begin(),v.end());//将v[begin(),end())区间中的元素拷贝给本身
vector(n,elem);//将n个elem拷贝给本身
vector(const vector& vec);//拷贝构造函数
/************************赋值操作*******************************/
assign(beg,end);//将[beg,end)区间中的数据拷贝赋值给本身
assign(n,elem);//将n个elem拷贝赋值给本身
vector& operator=(const vector& vec);//重载等号操作符
swap(vec);//将vec与本身元素交换
/************************大小操作*******************************/
size();//返回容器中元素的个数
empty();//判断容器是否为空
resize(int num);//重新指定容器长度为num,若变长则新位置填默认值,若变短,则末尾
                 //超出容器长度的元素被删除
                 //resize作用于容器的大小size,不会更改容器的容量capacity。
capacity();//容器的容量
reserve(int len);//容器预留len个元素的长度,预留位置若不初始化,元素不可访问
/************************数据存取*******************************/
at(int idx);//返回索引idx所指的数据,如果idx越界,抛出out_of_range异常
operator[];//返回idx所指的数据,越界时,运行直接报错
front();//返回容器中第一个数据元素
back();//返回容器中最后一个数据元素
/***********************插入和删除操作****************************/
insert(const_iterator pos,int count,elem);//在迭代器指向位置pos插入count个元素elem
push_back(elem);//尾部插入元素elem
pop_back();//删除最后一个元素
erase(const_iterator start,const_iterator end);//删除迭代器从start到end之间的元素
erase(const_iterator pos);//删除迭代器指向的元素
clear();//删除容器中所有元素

构造函数:

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

void printIntVector(vector<int>& v)
{
	for (vector<int>::iterator it = v.begin(); it != v.end(); it++)
	{
		cout << *it << " ";
	}
	cout << endl;
}
void test()
{
	//vector(n, elem);//将n个elem拷贝给本身
	vector<int> v1(10, 5);
	printIntVector(v1);
	//vector(v.begin(),v.end());//将v[begin(),end())区间中的元素拷贝给本身
	vector<int> v2(v1.begin() + 2, v1.end() - 2);
	printIntVector(v2);
	//vector(const vector& vec);//拷贝构造函数
	vector<int> v3(v2);
	printIntVector(v3);
	//将区间中的元素拷贝给本身
	int arr[] = { 1,2,3,4 };
	vector<int> v4(arr, arr + sizeof(arr) / sizeof(int));
	printIntVector(v4);
}
void main()
{
	test();
}

在这里插入图片描述
resize和swap联合修改容器容量:
首先用resize()将容器v的大小size变为10,接着在用容器v给匿名容器vector()初始化时调用复制构造函数,匿名容器的容量capacity会等于容器v的size为10,最后通过swap()函数将容器v与匿名容器交换,此时容器v的size为10,capacity为10 ,匿名容器的size为10,capacity为1024.交换完成后匿名容器会立即自动析构,内存空间得到释放。
在这里插入图片描述

void test2()
{
	vector<int> v;
	for (int i = 0; i < 100; i++)
	{
		v.push_back(i);
	}
	cout << "size=" << v.size() << endl;
	cout << "capacity=" << v.capacity() << endl;

	v.resize(10);//只能修改size,不能修改capacity
	cout << "size=" << v.size() << endl;
	cout << "capacity=" << v.capacity() << endl;

	//收缩容器容量
	vector<int>().swap(v);//使用匿名对象
	cout << "size=" << v.size() << endl;
	cout << "capacity=" << v.capacity() << endl;	
}

reserve:
预留空间用于提前已知需要向容器中存入多少数据的情况。如下例所示,没有reserve(),输出count为11,有reserve(),输出count为1。(另寻空间,将原空间值复制到新空间,释放原空间,三个步骤都会消耗时间)

void test3()
{
	vector<int> v;
	int* p = NULL;
	int count = 0;
	v.reserve(1000);
	for (int i = 0; i < 1000; i++)
	{
		v.push_back(i);
		if (p != &v[0])
		{
			p = &v[0];
			count++;
		}
	}
	cout << "count=" << count << endl;
}

在这里插入图片描述
erase与clear删除元素:

void test4()
{
	vector<int>v;
	v.push_back(10);
	v.push_back(20); 
	v.push_back(30);
	v.push_back(40);
	printIntVector(v);

	v.insert(v.begin() + 2, 3, 100);//从第三个位置往后插入3个100
	printIntVector(v);

	v.pop_back();//删除尾部元素
	printIntVector(v);

	v.erase(v.begin() + 2, v.end() - 1);//删除容器中第三个及以后的元素
	printIntVector(v);

	v.erase(v.begin() + 1);//删除容器中第二个元素
	printIntVector(v);
	cout << "size=" << v.size() << " capacity=" << v.capacity() << endl;

	v.clear();//删除容器中所有元素
	printIntVector(v);
	cout << "size=" << v.size() << " capacity=" << v.capacity() << endl;
}

在这里插入图片描述

6、vector容器存放自定义对象

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

class Person {
private:
	int age;
	string name;
public:
	Person() { age = 0; name = ""; cout << "Person无参构造函数!" << endl; }
	Person(int a, string n)
	{
		age = a;
		name = n;
		cout << "Person有参构造函数!" << endl;
	}
	Person(const Person& p) { age = p.age; name = p.name; cout << "拷贝构造!" << endl; }
	void showPerson() { cout << "age=" << age << " name=" << name << endl; }
	~Person()
	{
		cout << "析构函数!" << endl;
	}
};
void myPrint(Person& ob)
{
	ob.showPerson();
}
void test()
{
	Person ob1(18, "小明");
	Person ob2(20, "小芳");
	Person ob3(19, "小李");
	Person ob4(21, "小张");
	cout << "-------------------------------------------" << endl;

	vector<Person> v;
	//v.push_back(18, "小明");//error
	v.push_back(ob1);
	cout << "-------------------------------------------" << endl;
	v.push_back(ob2);
	cout << "-------------------------------------------" << endl;
	v.push_back(ob3);
	cout << "-------------------------------------------" << endl;
	v.push_back(ob4);
	cout << "-------------------------------------------" << endl;
	for_each(v.begin(), v.end(), myPrint);
	cout << "-------------------------------------------" << endl;
}
void main()
{
	test();
}

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值