STL-vector容器

前言

刚开始在网课上听老师讲这方面的东西时,又是vector又是迭代器,不知所云。只勉强知道可以用vector来动态创建数组,迭代器可以类似像指针一样移动(甚至以为迭代器就是指针),云里雾里,不了了之。但深入学习C++后,最近因为某些原因,又让我重新学习了这方面的知识,在网上和书中找了找相关的资料,终于有所领悟,所以想利用博客来做一些笔记。

STL提供了一-组表示容器、迭代器、函数对象和算法的模板。容器是一个与数组类似的单元,可以存储若千个值。STL 容器是同质的,即存储的值的类型相同;算法是完成特定任务( 如对数组进行排序或在链表中查找特定值)的处方;迭代器能够用来遍历容器的对象,与能够遍历数组的指针类似,是广义指针;函数对象是类似于函数的对象,可以是类对象或函数指针(包括函数名,因为函数名被用作指针)。STL使得能够构造各种容器(包括数组、队列和链表)和执行各种操作( 包括搜索、排序和随机排列)。
Alex Stepanov和Meng Lee在Hewlett-Packard实验室开发了STL,并于1994年发布其实现。ISO/ANSIC++委员会投票同意将其作为C++标准的组成部分。STL不是面向对象的编程,而是–种不同的编程模式一泛型编程( generic programming)。 这使得STL在功能和方法方面都很有趣。
以上摘自《C++ Primer Plus (第6版)中文版》

vector

vector是C++标准模板库中的部分内容,中文偶尔译作“容器”,但并不准确。它是一个多功能的,能够操作多种数据结构和算法的模板类和函数库。vector之所以被认为是一个容器,是因为它能够像容器一样存放各种类型的对象,简单地说,vector是一个能够存放任意类型的动态数组,能够增加和压缩数据。
以上摘自百度百科

利用vector动态添加元素 往vec_num中加入10个元素以及清空全部数据
std::vector<int> vec_num;//声明名为vec_num的vector整型容器
	for (int i = 0; i < 10; i++) {
    
    //初始化容器元素
		vec_num.push_back(i + 1);//动态添加元素
	}
	vec_num.clear();//清空全部数据
vector删除元素
按值删除
std::vector<int> vec_num;//声明名为vec_num的vector整型容器
	for (int i = 0; i < 10; i++) {
    
    //初始化容器元素
		vec_num.push_back(i + 1);//动态添加元素
	}
	std::vector<int>::iterator iter = find(vec_num.begin(), vec_num.end(), 3);//按顺序删除第一个值为3的元素,若有多个值为3的元素则默认删除第一个
	vec_num.erase(iter);
find函数说明

find函数在文件名为algorithm的头文件中,所以要使用它,请调用此头文件。

那么如何使用它呢

find(a,b,c),其中a为搜索的起点,b为搜索的终点,c为需要寻找的值。
而在容器中,其表示为find(iter1,iter2,x),需要注意的是,iter1与iter2是同一个容器的迭代器。当找到x时,find会返回一个x位置的迭代器,若容器中有多个值为x的元素,find则只返回其第一个。

利用find删除容器中指定下标元素
void deleteEle(vector<int>& vec,int index)
{
    
    
	vector<int>::iterator iter = vec.begin() + index;
	vec.erase(iter);
}
vector中end()方法需要注意的地方

实际上,end()是一个很特殊的地方,为了简要说明,这里引用《C++ Primer Plus (第6版)中文版》中的一张图,如下

在这里插入图片描述

从图中可以很直观的发现,我们认为的容器区间是100-132的范围内,但实际上,容器中还存在一个超尾元素,而end()就指向这个超尾元素。即图中的things.end()指向的并不是3,而是其后面的空字符的元素。所以总的取值范围为[begin,end)
那么如何访问3呢,很显然,只需要things.end()-1,使迭代器向左移一步即可。

迭代器与指针

什么是迭代器?它是一个广义指针。事实上,它可以是指针,也可以是一个可对其执行类似指针的操
作,如解除引用(如operator*( ))和递增(如operator++( )) .的对象。
以上摘自《C++ Primer Plus (第6版)中文版》

但其实只不过使行为上像是指针,实际上并不是一个真正的指针。以下代码即可体现出其差异。

#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int main()
{
    
    
	std::vector<int> vec_num;//声明名为vec_num的vector整型容器
	for (int i = 0; i < 10; i++) {
    
    //初始化容器元素
		vec_num.push_back(i + 1);//动态添加元素
	}
	for (vector<int>::iterator iter = vec_num.begin(); iter != vec_num.end(); iter++) {
    
    //由iter++可知iterator可像指针一样移动位置,但他们有着本质的不同
		cout << *(iter) << '\t';//解除引用,从此处可体现iterator有类似指针的一些性质(表现的像指针)
		printf("%p\t", iter) ;
		cout << *(vec_num.end() - 1);//从此处可看出end实际上指向的并不是我们初始化容器中的元素的最后一个,而是指向我们的最后一个元素后面一位,且不能直接访问
		//cout << *(vec_num.end());//若运行这句语句,即直接调用end()的话会抛出异常。
		cout << endl;
	}/*而从循环判断条件当中,vector.end()方法大有文章,end()字面理解应是所指的元素为容器的最后一个元素,
	 但其特殊的地方在于它比容器中所存的元素要多一个尾后元素(值为空),取值区间为[begin,end)
	 其优点暂且不知,但是如果不这样做,当begin()==end()的时候就无法判断是没有元素还是只有一个元素了
	 */
	cout<< endl;
	//从下面这段可以看出,指针移动时,其指向的内存地址也相应的改变,而iterator移动时,其地址并没有发生变化。
	int a[] = {
    
     1,2,3 };
	int* p_a = a;
	cout << *p_a << '\t';
	printf("%p\n", p_a);
	//cout << p_a<<endl;
	p_a++;
	cout << *p_a << '\t';
	printf("%p\n", p_a);
	//cout << p_a << endl;
	p_a++;
	cout << *p_a << '\t';
	printf("%p\n", p_a);
	//cout << p_a << endl;
	return 0;
}
运行代码后,可以发现,迭代器移动时,其地址没有发生变化,而指针的每一次移动,地址也在相应的发生变化,所以,其不是真正的指针。

以上为我对vector的理解,如理解有误,希望各位能够指出。

猜你喜欢

转载自blog.csdn.net/WildSky_/article/details/104254353