std vector 测试例子

话不多说,直接上代码:

#include <iostream>
#include <string>
#include <vector>

//基于C++11及以上的vector初始化及成员函数测试

int main()
{
	//vector官方见http://www.cplusplus.com/reference/vector/vector/,一共31个成员函数

	//https://blog.csdn.net/qq844352155/category_1765415.html也做了比较详细的分析,虽然我没看,感觉挺全的

	/*
	* 感悟:
	* 20211227:
	*	(1)提前开足够的capacity重要性,可以避免原始vector重新配置内部的存储器,可以提高代码效率,避免vector的reference、pointers、iterator失效;
	*	(2)大多数情况下,使用emplace、emplace_back代替insert、push_back
	*/

	//一、初始化,参考https://www.jianshu.com/p/d058866e0e10
	{
		//第1种,空初始化
		std::vector<int> v1;//size和capacity都是0
		std::cout << "size: " << v1.size() << ", capacity: " << v1.capacity() << std::endl;
		//第2种,默认初始化
		std::vector<int> v2(10);//size和capacity先预留,元素的值动态获取,一开始申请足够的大小以避免后面重新分配内存
		std::cout << "size: " << v2.size() << ", capacity: " << v2.capacity() << std::endl;
		//第3种
		std::vector<int> v3(10, 6);
		std::cout << "size: " << v3.size() << ", capacity: " << v3.capacity() << std::endl;
		//第4种,初始化列表
		std::vector<int> v4_1{ 1,2,3 };
		std::vector<int> v4_2 = { 1,8,4,9,3,2,6,5,7,4,2,3,7,9,5 };
		std::cout << "size: " << v4_1.size() << ", capacity: " << v4_1.capacity() << std::endl;
		std::cout << "size: " << v4_2.size() << ", capacity: " << v4_2.capacity() << std::endl;
		//第5种,拷贝初始化(深拷贝)
		std::vector<int> v5_1(v4_1);//拷贝后容量和元素都一致
		std::vector<int> v5_2 = v4_2;
		std::cout << "size: " << v5_1.size() << ", capacity: " << v5_1.capacity() << std::endl;
		std::cout << "size: " << v5_2.size() << ", capacity: " << v5_2.capacity() << std::endl;
		//第6种,迭代器初始化,不仅仅是vector初始化vector,只要有迭代器的东西都可以用来初始化vector
		int array[3] = { 7,8,9 };
		std::vector<int> v6_1(v4_2.begin() + 3, v4_2.end() - 2);//类似拷贝初始化
		std::vector<int> v6_2 = { v4_2.begin() + 3, v4_2.end() - 2 };//类似初始化列表
		std::vector<int> v6_3(std::begin(array) + 1, std::begin(array) + 2);//数组也可以用std::begin()
		std::vector<int> v6_4(array, array + 2);//数组也可以省略std::begin()
		std::cout << "size: " << v6_1.size() << ", capacity: " << v6_1.capacity() << std::endl;
		std::cout << "size: " << v6_2.size() << ", capacity: " << v6_2.capacity() << std::endl;
		std::cout << "size: " << v6_3.size() << ", capacity: " << v6_3.capacity() << std::endl;
		std::cout << "size: " << v6_4.size() << ", capacity: " << v6_4.capacity() << std::endl;
		std::cout << std::endl;
	}


	//二、往vector中插入元素push_back、emplace_back、insert、emplace
	{
		/*
		1、emplace_back和emplace是C++11才引入的,emplace_back是push_back的改良版,emplace是insert的改良版,
			几乎可以完全替代push_back,唯有少数不可,见https://www.zhihu.com/question/387522517/answer/1151720189
		2、当使用insert或emplace时,插入位置应该为[0-vector.size()],否则会出错,这里中括号指闭区间
		3、往vector中插入元素时,若capacity不够时进行插入,vector的capacity会改变,vector会重新配置内部的存储器,否则不会
		*/
		std::vector<int> v1{1,2,3};
		//v1.reserve(100);//通过开关这一行发现,若capacity不够时进行插入,capacity会改变,否则不会
		std::cout << "size: " << v1.size() << ", capacity: " << v1.capacity() << std::endl;
		v1.push_back(1);   //在末尾插入一个元素
		std::cout << "size: " << v1.size() << ", capacity: " << v1.capacity() << std::endl;
		v1.insert(v1.end() - 4, 3);   //在倒数第4个元素前插入一个元素
		std::cout << "size: " << v1.size() << ", capacity: " << v1.capacity() << std::endl;
		v1.insert(v1.begin(), 2);   //在指定位置,例如在开头插入一个元素
		std::cout << "size: " << v1.size() << ", capacity: " << v1.capacity() << std::endl;
		v1.insert(v1.end(), 3);   //在末尾插入一个元素,等同push_back
		std::cout << "size: " << v1.size() << ", capacity: " << v1.capacity() << std::endl;
		v1.insert(v1.begin() + 4, 100);   //在指定位置,例如在第5个元素前插入一个元素
		std::cout << "size: " << v1.size() << ", capacity: " << v1.capacity() << std::endl;
		v1.emplace(v1.begin(), 200);
		std::cout << "size: " << v1.size() << ", capacity: " << v1.capacity() << std::endl;
		v1.emplace(v1.begin() + 4, 300);
		std::cout << "size: " << v1.size() << ", capacity: " << v1.capacity() << std::endl;
		v1.emplace(v1.end(), 300);//在末尾插入一个元素,等同emplace_back
		std::cout << "size: " << v1.size() << ", capacity: " << v1.capacity() << std::endl;
		v1.emplace_back(400);
		std::cout << "size: " << v1.size() << ", capacity: " << v1.capacity() << std::endl;
		std::cout << std::endl;
	}


	//三、删除vector中元素,clear、erase、pop_back
	{
		/*
		clear会清空容器中元素,size变为0,但是capacity不变
		erase可以删除某一个位置的元素,或者某一段连续位置的元素,size会改变,但是capacity不变
		pop_back删除最后一个元素,size会改变,但是capacity不变
		*/
		std::vector<int> v1{ 1,2,3,4,5,6,7,8,9 };
		std::vector<int> v2(v1);
		std::cout << "size: " << v1.size() << ", capacity: " << v1.capacity() << std::endl;
		v2.clear();
		std::cout << "size: " << v2.size() << ", capacity: " << v2.capacity() << std::endl;
		v1.erase(v1.begin() + 0);
		std::cout << "size: " << v1.size() << ", capacity: " << v1.capacity() << std::endl;
		v1.erase(v1.begin() + 0, v1.begin() + 3);
		std::cout << "size: " << v1.size() << ", capacity: " << v1.capacity() << std::endl;
		v1.pop_back();
		std::cout << "size: " << v1.size() << ", capacity: " << v1.capacity() << std::endl;
		std::cout << std::endl;
	}


	//四、关于vector改变大小的几个函数size、resize、capacity、reserve
	{
		/*
		0、英文学习:reserve预留,reverse反转
		1、关于size、resize、capacity、reserve
		(1)size是指vector中元素的个数,capacity指当前vector能够容纳元素的数量
		(2)resize是会改变vector的size和capacity,那么新vector的size就为resize参数大小
			如果原vector的size小于resize的参数,里面的元素前面保持不变,后面用默认值或指定值填充
			如果原vector的size大于resize的参数,里面保留前n个元素,n为参数大小
			如果原vector的capacity小于resize的参数,新vector的capacity就为resize参数大小
			如果原vector的capacity大于resize的参数,新vector的capacity不变
		(3)reserve只能改变vector的capacity
			如果原vector的capacity小于reserve的参数,新vector的capacity就为reserve参数大小
			如果原vector的capacity大于reserve的参数,新vector的capacity不变
		*/
		{
			std::vector<int> v1{ 1,2,3 };
			std::cout << "size: " << v1.size() << ", capacity: " << v1.capacity() << std::endl;
			v1.resize(10, 1);//v1.resize(10);就等同于v1.resize(10, 0);
			std::cout << "size: " << v1.size() << ", capacity: " << v1.capacity() << std::endl;
			v1.resize(9, 2);
			std::cout << "size: " << v1.size() << ", capacity: " << v1.capacity() << std::endl;
			v1.reserve(5);
			std::cout << "size: " << v1.size() << ", capacity: " << v1.capacity() << std::endl;
			v1.reserve(20);
			std::cout << "size: " << v1.size() << ", capacity: " << v1.capacity() << std::endl;
		}
		/*
		2、要说明的是:
		(1)容器的大小一旦超过capacity的大小,vector会重新配置内部的存储器,
			导致和vector元素相关的所有reference、pointers、iterator都会失效;
		(2)内存的重新配置会很耗时间。
		因此,当我们使用vector时,如果能够提前预知其大小或者预知其大概的大小,都应该先使用reserve或resize提前分配一定的capacity
		如下例1、例2,程序开销是不一致的,而例3显示了iterator失效的情况
		*/
		//例1
		{
			std::vector<int> v;
			std::cout << "size: " << v.size() << ", capacity: " << v.capacity() << std::endl;
			v.emplace_back(1);
			std::cout << "size: " << v.size() << ", capacity: " << v.capacity() << std::endl;
			v.emplace_back(2);
			std::cout << "size: " << v.size() << ", capacity: " << v.capacity() << std::endl;
			v.emplace_back(3);
			std::cout << "size: " << v.size() << ", capacity: " << v.capacity() << std::endl;
		}
		//例2
		{
			std::vector<int> v;
			v.reserve(10);
			std::cout << "size: " << v.size() << ", capacity: " << v.capacity() << std::endl;
			v.emplace_back(1);
			std::cout << "size: " << v.size() << ", capacity: " << v.capacity() << std::endl;
			v.emplace_back(2);
			std::cout << "size: " << v.size() << ", capacity: " << v.capacity() << std::endl;
			v.emplace_back(3);
			std::cout << "size: " << v.size() << ", capacity: " << v.capacity() << std::endl;
		}
		//例3
		{
			std::vector<int> v{ 1,2,3 };
			std::cout << "size: " << v.size() << ", capacity: " << v.capacity() << std::endl;
			auto iter = v.begin();
			std::cout << "iter: " << *iter << std::endl;
			std::cout << "iter: " << *(++iter) << std::endl;
			v.emplace_back(4);
			//std::cout << "iter: " << *iter << std::endl;//这一句运行直接报错
		}
		std::cout <<  std::endl;
	}
	

	//五、关于vector元素位置的begin、end、cbegin、cend、rbegin、rend、crbegin、crend
	{
		/*
		其中cbegin、cend、crbegin、crend是C++11新加入
		begin()可以理解为第1个元素的前面,begin()+1就是第2个元素的前面,cbegin、rbegin、crbegin类似
		end()可以理解为最后1个元素的后面,end()就是倒数第2个元素的后面,cend、rend、crend类似
		begin、end: std::vector<int>::iterator
		cbegin、cend: std::vector<int>::const_iterator,用const迭代器修改容器的值不被允许
		rbegin、rend: std::vector<int>::reverse_iterator
		crbegin、crend: std::vector<int>::const_reverse_iterator,用const迭代器修改容器的值不被允许
		*/
		std::vector<int> v{ 5,6,7,8,9,1,2,3,4 };
		auto iter1 = v.begin();//std::vector<int>::iterator
		std::cout << "iter: " << *iter1 << std::endl;
		auto iter2 = v.end();
		std::cout << "iter: " << *--iter2 << std::endl;
		*iter1 = 100, std::cout << "iter: " << *iter1 << std::endl;
		auto c_iter1 = v.cbegin();//std::vector<int>::const_iterator
		std::cout << "c_iter: " << *c_iter1 << std::endl;
		auto c_iter2 = v.cend();
		std::cout << "c_iter: " << *--c_iter2 << std::endl;
		//*c_iter1 = 100, std::cout << "c_iter1: " << *c_iter1 << std::endl;//该操作不被允许
		auto r_iter1 = v.rbegin();//std::vector<int>::reverse_iterator
		std::cout << "r_iter: " << *r_iter1 << std::endl;
		auto r_iter2 = v.rend();
		std::cout << "r_iter: " << *--r_iter2 << std::endl;
		*r_iter1 = 100, std::cout << "r_iter1: " << *r_iter1 << std::endl;
		auto cr_iter1 = v.crbegin();//std::vector<int>::const_reverse_iterator
		std::cout << "cr_iter: " << *cr_iter1 << std::endl;
		auto cr_iter2 = v.crend();
		std::cout << "cr_iter: " << *--cr_iter2 << std::endl;
		//*cr_iter1 = 100, std::cout << "cr_iter1: " << *cr_iter1 << std::endl;//该操作不被允许
		std::cout << std::endl;
	}


	//六、操作符[]和=,获取元素的at、front、back
	{
		//1、操作符[]来获取某个位置的元素,用来读和写
		std::vector<int> v{ 5,6,7,8,9,1,2,3,4 };
		std::cout << "v[0]: " << v[0] << std::endl;
		std::cout << "v[8]: " << v[8] << std::endl;
		v[8] = 100;
		std::cout << "v[8]: " << v[8] << std::endl;
		//2、
		//3、at,与[]操作符类似,可以获取某个位置的元素,用来读和写
		std::cout << "v.at(1): " << v.at(1) << std::endl;
		v.at(1) = 100;
		std::cout << "v.at(1): " << v.at(1) << std::endl;
		//4、front、back,
		//front用来获取容器第一个元素,作用和v[0]、v.at(0)一致
		//back用来获取容器最后一个元素,作用和v[v.size() - 1]、v.at(v.size() - 1)一致
		auto f = v.front();
		auto b = v.back();
		std::cout << "f: " << f << std::endl;
		std::cout << "b: " << b << std::endl;
		std::cout << std::endl;
	}


	//七、其他成员函数assign、data、empty、get_allocator、max_size、shrink_to_fit、swap
	{
		{
			/*
			1、assign
			给容器赋值,与vector初始化相似,不同是可以给一个capacity更大的vector初始化前n个元素,或者capacity不足时扩展得更大
			*/
			std::vector<int> v1{ 1,2,3 };
			std::vector<int> v2(v1.begin(), v1.end());
			std::vector<int> v3;
			std::cout << "size: " << v3.size() << ", capacity: " << v3.capacity() << std::endl;
			v3.assign(v1.begin(), v1.end());
			std::cout << "size: " << v3.size() << ", capacity: " << v3.capacity() << std::endl;
			std::vector<int> v4(1), v5(5);
			std::cout << "size: " << v4.size() << ", capacity: " << v4.capacity() << std::endl;
			std::cout << "size: " << v5.size() << ", capacity: " << v5.capacity() << std::endl;
			v4.assign(v1.begin(), v1.end());
			v5.assign(v1.begin(), v1.end());
			std::cout << "size: " << v4.size() << ", capacity: " << v4.capacity() << std::endl;
			std::cout << "size: " << v5.size() << ", capacity: " << v5.capacity() << std::endl;
			std::cout << std::endl;
		}

		{
			/*
			2、data
			data就是获取一个指向vector元素的指针,与opencv中Mat的data类似
			*/
			std::vector<int> v1{ 1,2,3 };
			auto a = v1.data();
			std::cout << "a: " << *(a++) << std::endl;
			std::cout << "a: " << *(a++) << std::endl;
			std::cout << "a: " << *(a++) << std::endl;
			std::cout << "a: " << *(a++) << std::endl;//可以看到超过vector size的值就是不确定的
			std::cout << std::endl;
		}

		{
			//3、empty判断vector size的大小
			std::vector<int> v1, v2, v3;
			v2.reserve(3), v3.resize(3);
			std::cout << "size: " << v1.size() << ", capacity: " << v1.capacity() << std::endl;
			std::cout << "size: " << v2.size() << ", capacity: " << v2.capacity() << std::endl;
			std::cout << "size: " << v3.size() << ", capacity: " << v3.capacity() << std::endl;
			std::cout << "v1.empty: " << v1.empty() << std::endl;
			std::cout << "v2.empty: " << v2.empty() << std::endl;
			std::cout << "v3.empty: " << v3.empty() << std::endl;
			std::cout << std::endl;
		}

		{
			//4、get_allocator,返回内存分配器,暂时用不到
			std::vector<int> v1;
			auto x = v1.get_allocator();
		}

		{
			//5、max_size,容器所能容纳的最大元素数目,这是系统或者库所实施的限制,暂时用不到
			std::vector<int> v1;
			auto x = v1.max_size();
		}

		{
			/*
			6、shrink_to_fit,请求容器降低其容量和size匹配
			(1)由编译器决定是否真正释放多余的内存,该方法值是提出请求,是否要实现由编译器说了算
			(2)这可能导致重分配,但不会影响其size以及不能改变其元素
			*/
			std::vector<int> v1;
			v1.reserve(3);
			std::cout << "size: " << v1.size() << ", capacity: " << v1.capacity() << std::endl;
			v1.shrink_to_fit();
			std::cout << "size: " << v1.size() << ", capacity: " << v1.capacity() << std::endl;
			std::cout << std::endl;
		}

		{
			//7、swap,把两个相同类型的vector交换一下
			std::vector<int> v1{ 5,6,7,8,9,1,2,3,4 }, v2{ 1,2,3 };
			std::cout << "size: " << v1.size() << ", capacity: " << v1.capacity() << std::endl;
			std::cout << "size: " << v2.size() << ", capacity: " << v2.capacity() << std::endl;
			v1.swap(v2);
			std::cout << "size: " << v1.size() << ", capacity: " << v1.capacity() << std::endl;
			std::cout << "size: " << v2.size() << ", capacity: " << v2.capacity() << std::endl;
			std::cout << std::endl;
		}
	}

	return 0;
}

上一篇:Java Map集合迭代[详解]


下一篇:set接口的框架