【C++】vector常用接口

目录

1.vector简单介绍

2.vector类内函数

2.1构造函数 

2.2vector遍历

2.21 operate+[]

2.22迭代器遍历 

2.23范围for  

3.vector容量增长

3.1size和capacity 、resize和reverese

3.2max_size

4.增删查改 

4.1尾插 、尾删

4.2insert,erase 


1.vector简单介绍

上文我们介绍类字符类容器string,这次我们介绍一下它老弟vector

1.vector是一个泛型的顺序表容器。也就是说vector的空间是连续的。

2.vector存储的必须是相同类型的元素。当我们在一个vector里装入的是char的时候,就成了字符数组。

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

2.vector类内函数

2.1构造函数 

1.vector() 无参构造

vector <int> s1;

2.vector(size_type n, const value_type& val = value_type())构造并初始化n个val

vector <int> s2(10,3);

3、vector (const vector& x);  拷贝构造

vector <int> s2(10,3)
vector <int> s3(s2);   //进行拷贝构造

4.vector (InputIterator first, InputIterator last); 使用迭代器进行初始化构造

vector <int> s2(10,3);
vector <int> s3(s2.begin(), s2.end());
//通过迭代器获得s2的数据

这几个拷贝构造函数形式在各位眼中已经是老演员了,没啥新鲜感。

 补充:vector容器不能再向string一样直接使用cout直接进行屏幕打印,因为vector可以看做一个数组,想要遍历全部内容就需要其他方式了。

2.2vector遍历

2.21 operate+[]

这种遍历方式就是我们熟悉的下标+[]。

void test1()
{
	vector<int> v1;
	v1.push_back(1);
	v1.push_back(2);
	v1.push_back(3);
	v1.push_back(4);
	for (int i = 0; i < v1.size(); i++)
	{
		cout << v1[i] << " ";    //1 2 3 4 
	}
	cout << endl;

	vector<int>v2(5, 7);
	for (int i = 0; i < v2.size(); i++)
	{
		cout << v2[i] << endl;    //7 7 7 7 7 
	}

}

2.22迭代器遍历 

用迭代器进行遍历对我们来说已经见怪不怪了,接下来我们试一试vector如何遍历

 

 反向迭代器用法还是一样的

void test1()
{
	vector<int> v1;
	v1.push_back(1);
	v1.push_back(2);
	v1.push_back(3);
	v1.push_back(4);
	vector<int>::reverse_iterator it1 = v1.rbegin();
	while (it1 != v1.rend())
	{
		cout << *it1 << " ";;    //4 3 2 1 
		it1++;
	}
}

2.23范围for  

这个知识在string就已经出现了,接下来重点介绍一下。

让我们看一下这个代码

void test3()
{
		string strs[] = { "int", "char", "double", "float" };
		for (const auto& e : strs)
		{
			cout << e << " ";
		}
		cout << endl;
		system("pause");
	

}
int main()
{
	test3();
}

 auto :推演出范围变量的数据类型。 (当我们看到auto是就可以知道这是范围for了)

 e :e是范围变量的名称,该变量在循环迭代期间接受不同数组元素的值,即在第一次循环时,将数组的第一个元素拷贝给e,此时e的值是int;第二次循环时将数组的第二个元素拷贝给e,此时e的值是char;以此类推。

strs:要循环处理的数组的名称。

————————————————————————————————————————

1.为啥加引用

接下来说一说const auto& e,这个不需要&也能用

  范围for在遍历的时候,把数组的每一个元素的值拷贝给e,拷贝就要开辟空间,一定程度上降低了效率,所以加引用后可以节省空间,提高效率;而且若想要修改数组的内容,不加引用就无法修改,因为拷贝的值只是数组的一个副本,而加了引用之后,就是变量的别名,也就是变量本身,就可以进行修改操作。

2.为啥要加const?

为了auto推断出来的数据类型是对常量的引用,而且for循环中不会进行写操作,加上const更好一些。

3.在遍历的时候,是如何控制循环次数的?

范围for在循环处理数组时,可以自动知道数组中的元素个数,所以不需要使用变量控制条件控制其迭代次数,也不必担心数组下标越界问题,同时可以自动把数组中的每一个元素迭代一次,所以不需要再通过下标的自增去访问数组中的元素。

3.vector容量增长

这个跟string大差不差,就是没有length了。 

3.1size和capacity 、resize和reverese

Size

size指目前容器中实际有多少元素,对应的resize(size_type)会在容器尾添加或删除一些元素,来调整容器中实际的内容,使容器达到指定的大小。

Capacity

Capacity指最少要多少元素才会使其容量重新分配,对应reserve(size_type new_size)会设置这个capacity值,使它不小于所指定的new_size。

所以用reserve(size_type)只是扩大capacity值,这些内存空间可能还是“野”的,如果此时使用“[ ]”来访问,则可能会越界。而resize(size_t

size返回矢量中的元素数。(这是矢量中保存的实际对象数,不一定等于其存储容量

size_type size() const;

capacity:能力。返回当前为矢量分配的存储空间的大小,以元素表示。

size_type capacity() const;

容量不一定等于矢量大小。它可以相等或更大,额外的空间允许容纳增长,而无需在每次插入时重新分配。
请注意,此容量不会对矢量的大小有限制。当此容量耗尽并且需要更多容量时,容器会自动扩展它(重新分配存储空间)。向量大小的理论极限由成员max_size给出。

resize:调整大小。调整容器的大小,使其包含 n 个元素。

void resize (size_type n, value_type val = value_type());

1.如果 n 小于当前容器大小,则内容将减少到其前 n 个元素,删除超出的元素(并销毁它们)。

2.如果 n 大于当前容器大小,则通过在末尾插入所需数量的元素以达到 n 的大小来扩展内容。如果指定了 val,则新元素将初始化为 val 的副本,否则,它们将被值初始化。

3.如果 n 也大于当前容器容量,则会自动重新分配分配分配的存储空间。

容器的容量和容器大小不一样,一个杯子我装半杯水,这个容器大小现在是半杯水,我要装一杯半,这个大小就大于杯子的容量了,就要换杯子重开了。
 

reverse:保留  请求更改容量(和capacity对应)

void reserve (size_type n);

1.请求矢量容量至少足以包含 n 个元素。
2.如果 n 大于当前矢量容量,则该函数会导致容器重新分配其存储,将其容量增加到 n(或更大)。
3.在所有其他情况下,函数调用不会导致重新分配,并且矢量容量不受影响。
4.此函数对矢量大小没有影响,也无法更改其元素。

void test4()
{
	vector<int> v1(7, 4);
		cout << v1.size() << endl;
		cout << v1.capacity() << endl;

		v1.reserve(50);  // n是修改容器大小的
		cout << v1.capacity() << endl;//50
		//如果n < 当前容量大小,不做出任何改动
		v1.reserve(20);  //当前容器大小是50,20<50
		cout << v1.capacity() << endl;//50
}

resize有点不太好理解,我们单独介绍一下。

void test5()
{
	vector<int> v(7, 5);
	cout << v.size() << endl;//7
	cout << v.capacity() << endl;//7
	for (int i = 0; i < v.size(); i++)
	{
		cout << v[i] << " ";
	}
	cout << endl;
	v.resize(5); // n<size,size超出的部分被丢弃
	for (int i = 0; i < v.size(); i++)
	{
		cout << v[i] << " ";
	}
	cout << endl;
	//如果n的大小 > size和capacity,更新到n。超出的部分用5初始化
	v.resize(100, 5);
	cout << v.size() << endl;//100
	cout << v.capacity() << endl;//100
	//如果n的大小 < size,更新size到n,容量capacity不变
	v.resize(30);
	cout << v.size() << endl;//30
	cout << v.capacity() << endl;//100
	//如果n的大小 > size,且 < capacity,更新size到n,容量capacity不变
	v.resize(67);
	cout << v.size() << endl;//67
	cout << v.capacity() << endl;//100
}
int main()
{
	test5();
}

刚开始size1和capacity都是7,用了resize(100,5)我们用resize将大小从7扩大到100,超出的部分用5进行初始化。现在size是100.

我们又感觉size有点大了,resize(30),30<100,所以size的大小由100缩小至30。若是resize开辟的大小小于capacity,那么capacity不改变。

3.2max_size

max_size返回容器容纳的最大最大元素数。

size_type max_size() const;
void test()
{
	vector<int> v1;
	cout << v1.max_size() << endl;//1073741823
	vector<char> v2;
	cout << v2.max_size() << endl;//2147483647
}

4.增删查改 

vector容器相当于顺序表,它的空间是连续的。而list容器相当于链表。 

4.1尾插 、尾删

push_back:在矢量末尾的当前最后一个元素之后添加新元素。

void push_back (const value_type& val);
  • 这有效地将容器大小增加了 1,这会导致在且仅当新矢量大小超过当前矢量容量时自动重新分配分配的存储空间。

pop_back:删除最后一个元素

void pop_back();
  • 删除矢量中的最后一个元素,从而有效地将容器大小减小 1。
void test6()
{
	vector<int> v(5,3);  //3 3 3 3 3 
	v.push_back(1);     //3 3 3 3 3 1
	v.push_back(6);
	v.push_back(10);     //3 3 3 3 3 1 6 10
	for (int i = 0; i < v.size(); i++)
	{
		cout << v[i] << " ";
	}
	cout << endl;
	v.pop_back();   //3 3 3 3 3 1 6
	v.pop_back();   //3 3 3 3 3 1 
	for (int i = 0; i < v.size(); i++)
	{
		cout << v[i] << " ";
	}
	cout << endl;
}
int main()
{
	test6();
}

4.2insert,erase 

insert:插入元素(一般在pos位置插入val应用最广泛)

iterator insert (iterator position, const value_type& val);
  • 通过在指定位置的元素之前插入新元素来扩展矢量,从而有效地通过插入的元素数来增加容器大小
  • 这会导致自动重新分配分配的存储空间,当且仅当新矢量大小超过当前矢量容量时。
  • 由于向量使用数组作为其基础存储,因此在向量端以外的位置插入元素会导致容器将所有位于位置之后的元素重新定位到其新位置。与其他类型的序列容器(如列表或forward_list)为相同操作执行的操作相比,这通常是一个低效的操作
  • 这些参数确定插入了多少个元素以及将它们初始化为哪些值。

erase:删除元素  向量中删除单个元素(位置)或一系列元素([第一个,最后一个))。

iterator erase (iterator position);
iterator erase (iterator first, iterator last);
  • 这有效地减少了容器尺寸,减少了被破坏的元素的数量。
  • 由于矢量使用数组作为其基础存储,因此擦除矢量端以外的位置的元素会导致容器在擦除段后将所有元素重新定位到其新位置。与其他类型的序列容器(如列表forward_list)为相同操作执行的操作相比,这通常是一个低效的操作。
void test7()
{
	vector<int> v;
	v.push_back(1);
	v.push_back(5);
	v.push_back(10);
	for(int i = 0; i < v.size(); i++)
	{
		cout << v[i] << " ";
	}
	cout << endl;
	//insert
	v.insert(v.begin(), 0); //在下标为0的位置插入0
	v.insert(v.begin(), 2, 3);//在下标为0的位置往后插入两个3
	for (auto e : v)
		cout << e << " "; //3 3 0 1 5 10
	cout << endl;
	v.insert(v.begin() + 3, 2);//在下标为3的位置插入2
	for (const auto& e : v)
		cout << e << " "; //3 3 0 2 1 5 10
	cout << endl;
	cout << "----------------erase-----------------" << endl;
	//erase
	v.erase(v.begin()); //头删
	for (auto e : v)
		cout << e << " "; //3 0 2 1 5 10
	cout << endl;
	v.erase(v.begin() + 3); //删除下标为3的值
	for (auto e : v)
		cout << e << " "; //3 0 2  5 10
	cout << endl;
	//删除在该迭代器区间内的元素(左闭右开)
	v.erase(v.begin(), v.begin() + 3);//删除下标[0, 3)左闭右开的值
	for (auto e : v)
		cout << e << " ";//5 10
}

### 回答1: c++ 中的 vector 是一种封装了动态大小数组的容器类型,它可以存储任意类型的对象。与普通的数组相比,vector 具有自动扩展空间和自动回收空间的功能,可以帮助程序员更方便地管理内存。 使用 vector 的一般步骤如下: 1. 在程序中包含头文件 <vector>。 2. 定义一个 vector 变量,指定其中存储的元素类型。 3. 将元素加入 vector 中。vector 支持使用下标访问、插入和删除元素。也可以使用迭代器遍历 vector 中的元素。 示例代码如下: ``` #include <vector> #include <iostream> int main() { // 定义一个存储 int 类型元素的 vector std::vector<int> vec; // 将元素加入 vector 中 vec.push_back(1); vec.push_back(2); vec.push_back(3); // 使用下标访问 vector 中的元素 std::cout << "vec[0] = " << vec[0] << std::endl; // 使用迭代器遍历 vector 中的元素 for (auto iter = vec.begin(); iter != vec.end(); ++iter) { std::cout << *iter << " "; } std::cout << std::endl; return 0; } ``` 输出结果: ``` vec[0] = 1 1 2 3 ``` ### 回答2: C++中的vector是一个动态数组容器,它是C++标准模板库(STL)中的一个重要组成部分。通过vector,我们可以方便地存储和访问多个元素。 vector的实现方式是使用一个连续的内存块来存储数据。它的大小可以动态地增长或缩小,以适应需要存储的元素数量的变化。当元素数量超过当前内存块的大小时,vector会自动重新分配更大的内存块,并将原有的元素拷贝到新的内存块中。 vector的使用非常简单。我们可以使用push_back()函数在vector的末尾添加元素。如果vector中没有足够的内存来存储新的元素,push_back()函数会自动重新分配内存。我们也可以使用pop_back()函数删除vector末尾的元素。 vector还提供了一些其他的操作函数,比如可以用下标访问元素,可以获取vector中元素的数量和容量,可以插入或删除指定位置的元素等等。另外,vector还可以通过迭代器遍历元素。 使用vector有一些优点。首先,它提供了方便的操作接口,使得我们可以很容易地对元素进行增删改查。其次,vector在内存分配方面比较高效,它会自动管理内存的分配和释放,避免了手动管理内存的复杂性。 总之,vectorC++中非常常用的一个容器类,它提供了方便的操作接口和高效的内存分配,可以方便地存储和访问多个元素。在实际开发中,我们可以根据需要选择合适的容器类来存储和处理数据,而vector是一个不错的选择。 ### 回答3: C++vector是标准模板库(STL)中的一个容器,它允许动态分配内存,并以连续的方式存储元素。vector可以容纳任何类型的数据,如整型、浮点型、字符型、自定义类等。 在使用vector之前,需要包含头文件<vector>。 通过创建vector对象来实现,例如: ```cpp #include <vector> int main() { // 创建一个整型向量 std::vector<int> myVector; // 向向量添加元素 myVector.push_back(1); myVector.push_back(2); myVector.push_back(3); // 修改向量中的元素 myVector[0] = 4; // 遍历输出向量中的元素 for (int i = 0; i < myVector.size(); i++) { std::cout << myVector[i] << " "; } return 0; } ``` 上述代码首先创建了一个整型向量`myVector`,然后使用`push_back()`函数向向量中添加元素。可以使用索引操作符`[]`来修改向量中的元素,同时可以使用`size()`函数获取向量的大小。 最后,通过遍历循环将向量中的元素输出到控制台。 除了`push_back()`函数,vector还提供了其他一些常用的操作函数,如`pop_back()`删除向量的最后一个元素,`insert()`在指定位置插入元素,`erase()`删除指定位置的元素等等。 总之,C++vector是一个非常方便和强大的容器,可以根据需要动态管理内存,并提供了许多便捷的操作函数来方便地处理数据。
评论 19
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值