0
点赞
收藏
分享

微信扫一扫

【DevOps】Elasticsearch在Ubuntu 20.04上的安装与配置:详细指南

凯约 2024-05-28 阅读 16

vector的介绍

vector的使用

下面是对于vector的基本用法的讲解

vector的初始化

(constructor)构造函数声明接口说明
vector()(重点)无参构造
vector(size_type n, const value_type& val = value_type())构造并初始化n个val
vector (const vector& x); (重点)拷贝构造
vector (InputIterator first, InputIterator last);使用迭代器进行初始化构造

主要使用的是无参构造和拷贝构造,其他两种不常用,下面代码一并介绍

void test1()
{
	//1.vector()(重点) | 无参构造 
	vector<int> v1;
	v1.push_back(1);
	v1.push_back(2);
	v1.push_back(3);
	v1.push_back(4);
	for (auto c : v1)
	{
		cout << c << " ";
	}
	cout << endl;

	//2.vector(size_type n, const value_type& val = value_type()) | 构造并初始化n个val
	vector<int> v2(10, 0);
	for (auto c : v2)
	{
		cout << c << " ";
	}
	cout << endl;

	//3.vector(const vector & x); (重点) | 拷贝构造        
	vector<int> v3(v1);
	for (auto c : v3)
	{
		cout << c << " ";
	}
	cout << endl;

	//4.vector(InputIterator first, InputIterator last);
	vector<int> v4(v2.begin(), v2.end());
	for (auto c : v4)
	{
		cout << c << " ";
	}
	cout << endl;
}
int main()
{
	test1();
	return 0;
}

vector iterator迭代器的使用

vector的迭代器有两种,正向和反向迭代器

正向:begin() 和 end() 分别表示获取第一个数据的位置,获取最后一个数据的下一个位置

反向:rbegin() 和 rend() 分别表示获取最后一个数据的位置,获取第一个元素的前一个位置

//迭代器的名称分别为  iterator  和reverse_iterator
void test2()
{
	vector<int> v;
	v.push_back(1);
	v.push_back(2);
	v.push_back(3);
	v.push_back(4);
	v.push_back(5);
	vector<int>::iterator it = v.begin();
	while (it != v.end())
	{
		cout << *it << " ";
		++it;
	}
	cout << endl;
	//auto rit=v.rbegin();
	vector<int>::reverse_iterator rit = v.rbegin();
	while (rit != v.rend())
	{
		cout << *rit << " ";
		++rit;
	}
	cout << endl;
	for (auto c : v)
	{
		cout << c << " ";
	}
	cout << endl;
}
int main()
{
	test2();
	return 0;
}

vector 空间增长问题

使用几种函数来管理和查看vector的空间

容量空间接口说明
size获取数据个数
capacity获取容量大小
empty判断是否为空
resize改变vector的size
reserve改变vector的capacity

主要是对于resize和reserve的使用,empty就是判别是否为空,size和capacity是查看当前vector的数据个数和容量

void test3()
{
	vector<int> v;
	v.push_back(1);
	v.push_back(2);
	v.push_back(3);
	v.push_back(4);
	v.push_back(5);

	cout << v.size() << endl;
	cout << v.capacity() << endl;

	v.resize(20);
	cout << "更改size为20" << endl;
	cout << v.size() << endl;
	cout << v.capacity() << endl;

	v.reserve(40);
	cout << "更改capacity为40" << endl;
	cout << v.size() << endl;
	cout << v.capacity() << endl;


	v.resize(50);
	cout << "更改size为50" << endl;
	cout << v.size() << endl;
	cout << v.capacity() << endl;
}
void test4()
{
	vector<int> v;
	size_t ans = v.capacity();
	for (int i = 0; i < 200; i++)
	{
		v.push_back(i);
		if (ans != v.capacity())
		{
			cout << "capacity为:" << ans << endl ;
		}
		ans = v.capacity();
	}
}

int main()
{
	test4();
	return 0;
}

注意:capacity的增长倍数是由环境决定的,vs下在1.5倍数左右,在Linux下近乎2倍,且关于resize和reserve,我们只需要知道resize底层是调用reserve的,满足size<=capacity

vector的增删改查

vector的增删改查接口说明
push_back尾插
pop_back尾删
find查找指定的数据,返回下标(在算法模块,不在vector的成员函数中)
insert在pos位置上插入指定数值val
erase删除指定pos位置上的数据
swap交换两个vector对象的数据空间
operator[ ]和数组一样,通过下标方括号来访问vector的数据

STL分为两大模块,容器和算法,容器例如vector、list、set等,算法是在头文件<algorithm>中,是将容器中通用的函数归档在<algorithm>中,按照迭代器的不同,不同容器能使用相同或不同的函数。

push_back 和 pop_back 以及operator[ ]的使用

简单理解,不必做详解

void test5()
{
	vector<int> v;
	v.push_back(1);
	v.push_back(2);
	v.push_back(3);
	v.push_back(4);
	v.push_back(5);
	//push_back的使用,传参val   const value_type& val  value_type实际就是T 模板类
	for (auto c : v)
	{
		cout << c << " ";
	}
	cout << endl;
	//pop_back 的使用,不必传参,尾删
	v.pop_back();   
	for (auto c : v)
	{
		cout << c << " ";
	}
	cout << endl;
	//operator[]的使用   可以访问指定下标位置元素,也可赋值
	cout << v[2] << endl;
	v[2] = 10;
	cout << v[2] << endl;
}
int main()
{
	test5();
	return 0;
}

find

在<algorithm>算法中,InputIterator find (InputIterator first, InputIterator last, const T& val);

#include<algorithm>
void test6()
{
	vector<int> v;
	v.push_back(1);
	v.push_back(2);
	v.push_back(3);
	v.push_back(4);
	auto it =find(v.begin(), v.end(), 5);
	if (it != v.end())
	{
		cout << *it << endl;
	}
	else if(it == v.end())
	{
		cout << "没有找到val,返回的是v.end()" << endl;
	}
}
int main()
{
	test6();
	return 0;
}

insert

insert的插入,实际上就是先得到要插入的数值个数n,然后将vector中的元素后移n位,然后依次填入插入的数据

void test7()
{
	vector<int> v;
	v.push_back(1);
	v.push_back(2);
	v.push_back(3);
	v.push_back(4);
	for (auto c : v)
	{
		cout << c << " ";
	}
	cout << endl;
	//1.iterator insert (iterator position, const value_type& val); 
	auto it=v.insert(v.begin() + 1, 10);
	cout << "返回迭代器指向的数值为:" << *it << endl;
	for (auto c : v)
	{
		cout << c << " ";
	}
	cout << endl;

	//2.void insert (iterator position, size_type n, const value_type& val);
	v.insert(v.begin(), 5, 6);
	for (auto c : v)
	{
		cout << c << " ";
	}
	cout << endl;

	//3.void insert(iterator position, InputIterator first, InputIterator last);
	v.insert(v.begin(), v.begin(), v.end());
	for (auto c : v)
	{
		cout << c << " ";
	}
	cout << endl;

	vector<int> v1;  //后两个参数,只要是迭代器即可,可以是其他容器的迭代器数据插入过来
	v1.insert(v1.begin(), v.begin(), v.begin()+6);
	for (auto c : v1)
	{
		cout << c << " ";
	}
	cout << endl;

}
int main()
{
	test7();
	return 0;
}

erase

void test8()
{
	vector<int> v;
	v.push_back(1);
	v.push_back(2);
	v.push_back(3);
	v.push_back(4);

	//指定pos迭代器删除
	auto it =v.erase(v.begin());  //返回的是删除之后的v.begin()
	cout << *it << endl;
	for (auto c : v)
	{
		cout << c << " ";
	}
	cout << endl;  
	//区间删除
	it=v.erase(v.begin() + 1, v.begin()+2);
	cout << *it << endl;		//返回的是删除之后的v.begin() + 1   但是要注意越界问题
	for (auto c : v)
	{
		cout << c << " ";
	}
	cout << endl;
}
int main()
{
	test8();
	return 0;
}

迭代器失效

迭代器的主要作用就是让算法能够不用关心底层数据结构,其底层实际就是一个指针,或者是对指针进行了封装,所以迭代器失效实际上就是迭代器底层对应指针所指向的空间被销毁了,而使用一窥啊已经倍释放的空间,当继续使用已经失效的迭代器,会造成程序崩溃。

第一种场景,统一导致迭代器失效的是,由于增加元素或者手动扩容,导致vector扩容,然而扩容机制,底层是新建一个T指针数组,拷贝原有数据到新数组中,然后释放原来的数组空间,所以迭代器会失效(此时的迭代器指向的是一块被释放的空间),导致程序崩溃

void test9()
{
	vector<int> v;
	v.push_back(1);
	v.push_back(2);
	v.push_back(3);
	v.push_back(4);

	//底层的改变实际上就是是否扩容了
	
	//先获得当前vector的首元素的迭代器
	vector<int>::iterator it = v.begin();  
	cout << *it << endl;
	//1.如果经历了resize ,触发扩容,迭代器失效    代码为 -1073741819。
	//v.resize(50, 0);
	//cout << *it << endl;
	
	//2.如果使用reserve手动扩容的话,也会导致迭代器失效
	//v.reserve(100);
	//cout << *it << endl;  //代码为 -1073741819。

	//3.如果是插入元素,导致扩容,也会导致迭代器失效
	//v.insert(v.begin(), 100, 1);
	//cout << *it << endl;    //代码为 -1073741819。

	//4.如果是push_back 导致扩容,也会发生迭代器失效
	for (int i = 0; i < 100; i++)
	{
		v.push_back(i);
	}
	cout << *it << endl;   //代码为 -1073741819。
}
int main()
{
	test9();
	return 0;
}

第二种场景,erase函数,删除指定pos位置数据,或者删除迭代器区间的数据。我们先用auto it=v.begin()+5,获得迭代器,然后我们删除一个元素,删除之后有两种可能:1.it指向的位置还有元素,那么按照道理来说 cout一下还是能正常输出数值 2.it位置已经没有元素了,此时it指向的空间已经是vector.end()之后了,再次访问it的时候,就会报错,相当于越界了。

综合上述两种可能,因此删除vector中任意位置上元素时,vs就认为该位置迭代器失效了。

void test10()
{
	vector<int> v;
	v.push_back(1);
	v.push_back(2);
	v.push_back(3);
	v.push_back(4);

	auto it = v.begin();
	v.erase(v.begin());
	//v.erase(v.begin(), v.end());
	cout << *it << endl;  //代码为 -1073741819
}
int main()
{
	test10();
	return 0;
}

迭代器失效解决办法:在使用前,对迭代器重新赋值即可。

总结

vector的优点:

1.支持随机访问(以[]的方式)

2.cpu高速缓存效率高

vector的缺点:

1.中间和头部删除元素效率低(要移动数组元素)

2.扩容问题(扩容会导致迭代器失效)

举报

相关推荐

0 条评论