C++(15)——vector

       在前几篇针对于string进行介绍的文章中提到了,对于string,可以将其看作是一个字符数组。对于本篇文章的主题vector,可以将其看作数据结构中的顺序表,其大体的特点如下:

1. vector是表示可变大小数组的序列容器。
2. 就像数组一样,vector也采用的连续存储空间来存储元素。也就是意味着可以采用下标对vector的元素
进行访问,和数组一样高效。但是又不像数组,它的大小是可以动态改变的,而且它的大小会被容器自动处理。
3. 本质讲,vector使用动态分配数组来存储它的元素。当新元素插入时候,这个数组需要被重新分配大小为了增加存储空间。其做法是,分配一个新的数组,然后将全部元素移到这个数组。就时间而言,这是一个相对代价高的任务,因为每当一个新的元素加入到容器的时候,vector并不会每次都重分配大小。
4. vector分配空间策略:vector会分配一些额外的空间以适应可能的增长,因为存储空间比实际需要的存储空间更大。不同的库采用不同的策略权衡空间的使用和重新分配。但是无论如何,重新分配都应该是对数增长的间隔大小,以至于在末尾插入一个元素的时候是在常数时间的复杂度完成的。
5. 因此,vector占用了更多的存储空间,为了获得管理存储空间的能力,并且以一种有效的方式增
长。
6. 与其它动态序列容器相比(deque, list and forward_list), vector在访问元素的时候更加高效,在末尾添加和删除元素相对高效。对于其它不在末尾的删除和插入操作,效率更低。比起list和forward_list统一的迭代器和引用更好。

     在简单了解了关于vector的特性后,下面将给出vector的相关函数,以及部分函数的使用方法

1.constructor——构造函数:

对于vector中的构造函数的种类如下:

vector()                                                    //无参构造
                                               
vector(size_type n, const value_type& val = value_type()   //构造并初始化n个val

vector (const vector& x);                                   //拷贝构造
 
vector (InputIterator first, InputIterator last);            //使用迭代器进行初始化构造

在使用vector的相关函数之前,需要包含头文件vector,即:

#include

1.1 vector() :

对于vector的无参构造较为简单,这里只给出相应的代码,不做过多解释:

int main()
{
	vector v; //无参构造

	return 0;
}


1.2 vector(size_type n, const value_type& val = value_type() :

使用方法如下:

int main()
{
	vector v(10, 1); 
	return 0;
}

对于vector,可以像string一样通过不同的方式来对内容进行访问,例如:

int main()
{
	vector v1(10, 1);

	for (size_t i = 0; i < v1.size(); i++)
	{
		cout << v1[i];
	}
	return 0;
}

运行结果如下:
C++(15)——vector_第1张图片

       此外,在vector中同样可以使用迭代器对内容进行访问,这一部分内容将在下面介绍迭代器的部分统一给出。

1.3 vector (InputIterator first, InputIterator last):

函数的构造是利用迭代器进行构造的。例如,假设用上文中的v1,来构建一个新的v2,方法如下:

vector v2(v1.begin(), v1.end());

	for (size_t i = 0; i < v2.size(); i++)
	{
		cout << v2[i] << ' ';
	}

运行结果如下:
C++(15)——vector_第2张图片
 

1.4 vector (const vector& x):

拷贝构造函数,具体使用如下:

int main()
{

	vector v1(10, 1);
	vector v2(v1.begin(), v1.end());
	vector v3(v2);

	cout << endl << "vector v3:";
	for (auto ch : v3)
	{
		cout << ch << ' ';
	}

	return 0;
}

运行结果如下:
C++(15)——vector_第3张图片

2. iterator——迭代器:

C++(15)——vector_第4张图片

上图展示了vector中不同的迭代器,其具体使用方法如下:

2.1 begin()、end():

int main()
{
	vector v1(10, 1);
	vector::iterator it1 = v1.begin();

	while(it1 != v1.end())
	{
		cout << *it1 << ' ';
		it1++;
	}
	return 0;
}

运行结果如下:
C++(15)——vector_第5张图片

2.2 rbegin()、rend():

为了更好的演示rbegin,rend函数的作用,此处先引入一个新的函数push_back其作用可以看作顺序表中的尾插。使用push_back函数向vector中插入1,2,3,4,5五个元素,即:

vector v1;
	v1.push_back(1);
	v1.push_back(2);
	v1.push_back(3);
	v1.push_back(4);
	v1.push_back(5);

通过反向迭代器rbegin,rend对其进行访问,运行结果如下:
 

int main()
{
vector v1;
	v1.push_back(1);
	v1.push_back(2);
	v1.push_back(3);
	v1.push_back(4);
	v1.push_back(5);

	vector::iterator it1 = v1.begin();

	while (it2 != v1.rend())
	{
		cout << *it2 << ' ';
		it2++;
	}

    return 0;
}

运行结果如下:
C++(15)——vector_第6张图片
 

2.3 cbegin()、cend():

begin,end函数主要是针对于非const对象,而cbegin,cend是针对于const对象。

对于二者的差距,表现为是否可以修改迭代器指向的内容,例如,对于非const对象:

vector v1(10, 1);
	vector::iterator it1 = v1.begin();
	while(it1 != v1.end())
	{
		(*it1)++;
		cout << *it1 << ' ';
		it1++;
	}

代码运行结果如下:

C++(15)——vector_第7张图片

对于一个const对象,即:

const vector v2(10, 1);
	vector::const_iterator it2 = v2.cbegin();
	while(it2 != v2.cend())
	{
		(*it2)++;
		cout << *it2 << ' ';
		it2++;
	}

此时编译器会报错,错误内容如下:
C++(15)——vector_第8张图片

3.capacity——容量操作:

3.1 capacity():

用于检测vector容器的容量以及内容长度,具体使用方法如下:

	vector v(10,1);
	cout<<"v.capacity= " << v.capacity() << endl;
	cout<<"v.size= " << v.size() << endl;

运行结果如下:

C++(15)——vector_第9张图片

对于reserve()resize()虽然都可以达到改变容量的效果,但是却又一定的差别

对于reserve(),假设需要将函数扩容到n,即reserve(n),如果n>capacity,则改变容器的capacity,不会改变size。并且不会影响容器中的内容例如:

vector v(10,1);
	cout<<"扩容前:"<<"v.capacity= " << v.capacity() << endl;
	cout<<"扩容前:"<<"v.size= " << v.size() << endl;

	v.reserve(100);
	
	cout<<"扩容后:" << v.capacity() << endl;
	cout<<"扩容后:" << v.size() << endl;

运行结果如下:

C++(15)——vector_第10张图片

n<capacity时,reserve函数对capacitysize,容器中的内容均不会产生影响,例如:
 

vector v(10,1);
	cout<<"缩容前:"<<"v.capacity= " << v.capacity() << endl;
	cout<<"缩容前:"<<"v.size= " << v.size() << endl;
	cout << "内容:";
	for (auto ch : v)
	{
		cout << ch << ' ';
	}
	cout << endl;
	v.reserve(5);
	
	cout<<"缩容后:" << v.capacity() << endl;
	cout<<"缩容后:" << v.size() << endl;
	cout << "内容";
	for (auto ch : v)
	{
		cout << ch << ' ';
	}

运行结果如下:
C++(15)——vector_第11张图片

3.2 resize():

对于resize(n),假如n <sizeresize函数并不会影响容器的capacity,但是会影响容器中的内容,以及容器的size。为了方便演示,使用push_back创建以下容器:

vector v1;
	v1.push_back(1);
	v1.push_back(2);
	v1.push_back(3);
	v1.push_back(4);
	v1.push_back(5);
	v1.push_back(6);
	v1.push_back(7);
	v1.push_back(8);
	v1.push_back(9);
	v1.push_back(10);

对其使用函数resize,代码如下:

cout << "缩容前:" << "v.capacity= " << v1.capacity() << endl;
	cout << "缩容前:" << "v.size= " << v1.size() << endl;
	cout << "内容:";
	for (auto ch : v1)
	{
		cout << ch << ' ';
	}
	cout << endl;
	v1.resize(5);

	cout << "缩容后:" << v1.capacity() << endl;
	cout << "缩容后:" << v1.size() << endl;
	cout << "内容";
	for (auto ch : v1)
	{
		cout << ch << ' ';
	}

代码运行结果如下:
C++(15)——vector_第12张图片

n>capacity时,resize会通过向容器的末端插入元素的方式来达到扩容的目的,并且会同时改变容器的capacitysize。并且,如果不人为给出扩容时插入的元素,则默认插入0,否则插入给出的元素,例如:

cout << "缩容前:" << "v.capacity= " << v1.capacity() << endl;
	cout << "缩容前:" << "v.size= " << v1.size() << endl;
	cout << "内容:";
	for (auto ch : v1)
	{
		cout << ch << ' ';
	}
	cout << endl;
	//默认插入0
	v1.resize(15);

	cout << "缩容后:" << v1.capacity() << endl;
	cout << "缩容后:" << v1.size() << endl;
	cout << "内容";
	for (auto ch : v1)
	{
		cout << ch << ' ';
	}

代码运行结果如下:
C++(15)——vector_第13张图片

如果给定末端插入元素1,即:

cout << "缩容前:" << "v.capacity= " << v1.capacity() << endl;
	cout << "缩容前:" << "v.size= " << v1.size() << endl;
	cout << "内容:";
	for (auto ch : v1)
	{
		cout << ch << ' ';
	}
	cout << endl;
	v1.resize(15,1);

	cout << "缩容后:" << v1.capacity() << endl;
	cout << "缩容后:" << v1.size() << endl;
	cout << "内容";
	for (auto ch : v1)
	{
		cout << ch << ' ';
	}

代码运行结果如下:

C++(15)——vector_第14张图片

你可能感兴趣的:(C++,c++,开发语言)