【C++】vector的使用

目录

一、vector的介绍

二、vector的使用

2.1构造函数

🎉vector() 默认构造

🎉vetor(const vector& x) 拷贝构造

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

🎉vector(Inputlterator first , InputIterator last,const allocator_type& alloc=allocator_type()) 使用迭代器进行初始化构造

2.2遍历

🎉迭代器 iterator

2.3对容量的操作

🎉size() 获取数据个数

🎉capacity() 获取容量大小

🎉reserve() 改变vector的capacity 

🎉resize() 改变vector的size

2.4增删查改

🎉push_back() 尾插

🎉pop_back()  尾删

🎉operator[ ] 像数组一样访问

🎉find()  查找(这个是算法模块实现,不是vector的成员接口)

🎉insert() 在position之前插入val

🎉erase() 删除position位置的数据


一、vector的介绍

Vector是表示大小可以改变的数组的序列容器。

与数组一样,vector对其元素使用连续的存储位置,这意味着也可以使用指向其元素的常规指针上的偏移量来访问其元素,并且与数组中的效率一样高。但与数组不同,它们的大小可以动态变化,其存储由容器自动处理。

 在内部,vector使用动态分配的数组来存储它们的元素。当插入新元素时,可能需要重新分配此数组以增加大小,这意味着分配一个新数组并将所有元素移动到其中。就处理时间而言,这是一项相对昂贵的任务,因此,vector不会在每次将元素添加到容器时重新分配。

相反,vector容器可以分配一些额外的存储空间来适应可能的增长,因此容器的实际容量可能大于容纳其元素所需的存储空间(即其大小)。库可以实现不同的增长策略来平衡内存使用和重新分配,但在任何情况下,重新分配都应该只以对数增长的间隔发生,这样在vector末尾插入单个元素就可以以摊销的恒定时间复杂度提供(见push_back)。

因此,与数组相比,向量消耗更多的内存,以换取管理存储和以高效方式动态增长的能力。

 与其他动态序列容器(双端队列、列表和forward_lists)相比,vector访问其元素(就像数组一样)非常高效,并且从其末尾添加或删除元素也相对高效。对于涉及在末尾以外的位置插入或删除元素的操作,它们的性能比其他操作差,并且迭代器和引用的一致性不如列表和forward_lists。 

二、vector的使用

2.1构造函数

🎉vector() 默认构造

创建一个空的vector对象,不含任何元素。

vector<int> v1;

🎉vetor(const vector& x) 拷贝构造

它创建一个新的vector实例。

vector<int> v2(v1);

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

这个函数创建了一个含有n个元素的vector,每个函数都是val的副本。

vector<int> v3(4,100);//创建4个整型为100的值

🎉vector(Inputlterator first , InputIterator last,const allocator_type& alloc=allocator_type()) 使用迭代器进行初始化构造

这个构造函数使用两个迭代器 first last ,这两个迭代器指定了一个序列的的范围,来创建vector。这个范围包括从 first last 之间的所有元素,但不包括 last 指向的元素。 

vector<int> v4(v3.begin(),v3.end());

2.2遍历

🎉迭代器 iterator

    vector<int> v(10,1);
	// const对象使用const迭代器进行遍历打印
	vector<int>::const_iterator it = v.begin();
	while (it != v.end())
	{
		cout << *it << " ";
		++it;
	}
	cout << endl;

 这些接口的用法类似。

2.3对容量的操作

🎉size() 获取数据个数

与string类相似。

🎉capacity() 获取容量大小

// 测试vector的默认扩容机制
// vs:按照1.5倍方式扩容
// linux:按照2倍方式扩容

	size_t sz;
	vector<int> v;
	sz = v.capacity();
	cout << "making v grow:\n";
	for (int i = 0; i < 100; ++i) 
	{
		v.push_back(i);
		if (sz != v.capacity()) 
		{
			sz = v.capacity();
			cout << "capacity changed: " << sz << '\n';
		}
	}

vs下capacity是按1.5倍增长 

🎉reserve() 改变vector的capacity 

用来预先开辟容量大小,减少扩容的次数:(开空间不初始化)

// 如果已经确定vector中要存储元素大概个数,可以提前将空间设置足够
// 就可以避免边插入边扩容导致效率低下的问题了

 vector<int> v;
 size_t sz = v.capacity();
 v.reserve(100); // 提前将容量设置好,可以避免一遍插入一遍扩容
 cout << "making bar grow:\n";
 for (int i = 0; i < 100; ++i) 
 {
     v.push_back(i);
     if (sz != v.capacity())
     {
       sz = v.capacity();
       cout << "capacity changed: " << sz << '\n';
     }
 }

🎉resize() 改变vector的size

1.只会改变size的大小,不会改变capacity的大小。resize开空间并初始化。

2.resize不会进行缩容,如果想要缩容,我们可以调用 shrink_to_fit();

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

如果n大于当前容器大小,则通过在末尾插入尽可能多的元素来扩展内容,以达到n的大小。如果指定了val,则新元素将初始化为val的副本,否则将进行值初始化。

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

请注意,此函数通过插入或删除容器中的元素来更改容器的实际内容。

2.4增删查改

🎉push_back() 尾插

直接尾插一个元素。 

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

	auto it = v.begin();
	while (it != v.end()) 
	{
		cout << *it << " ";
		++it;
	}
	cout << endl;

输出:1 2 3 4 

🎉pop_back()  尾删

直接删除尾部元素。

    v.pop_back();
	v.pop_back();

	it = v.begin();
	while (it != v.end()) 
	{
		cout << *it << " ";
		++it;
	}
	cout << endl;

输出:1 2 

🎉operator[ ] 像数组一样访问

一个类似的成员函数vector::at与此运算符函数具有相同的行为,除了vector::at被绑定检查,并通过抛出out_of_range异常来发出请求位置是否超出范围的信号。
可移植程序不应使用超出范围的参数n调用此函数,因为这会导致未定义的行为。 

	vector<int> v{ 1, 2, 3, 4 };

	// 通过[]读写第0个位置。
	v[0] = 10;
	cout << v[0] << endl;

	// 1. 使用for+[]小标方式遍历
	for (size_t i = 0; i < v.size(); ++i)
		cout << v[i] << " ";
	cout << endl;

	vector<int> swapv;
	swapv.swap(v);

	cout << "v data:";
	for (size_t i = 0; i < v.size(); ++i)
		cout << v[i] << " ";
	cout << endl;

	// 2. 使用迭代器遍历
	cout << "swapv data:";
	auto it = swapv.begin();
	while (it != swapv.end())
	{
		cout << *it << " ";
		++it;
	}

	// 3. 使用范围for遍历
	for (auto x : v)
		cout << x << " ";
	cout << endl;

🎉find()  查找(这个是算法模块实现,不是vector的成员接口)

vector库没有find函数,我们使用的是算法库中的find,使用时要包含<algorithm>头文件

 参数:

1.first last 是输入迭代器

将迭代器输入到序列的初始和最终位置。搜索的范围是 [first,last),它包含firstlast之间的所有元素,包括first指向的元素,但不包括last指向的元素

2.val要查找的值:在范围内搜索的值。
find函数会使用元素类型的operator==来比较每个元素是否跟val相等。

3.返回值:

(1)找到:返回一个迭代器,指向范围内第一个与val相等的元素。

(2)如果没有匹配的元素,函数将返回最后一个(last),表示查找失败。

	// 使用列表方式初始化,C++11新语法
	vector<int> v{ 1, 2, 3, 4 };

    auto pos = find(v.begin(), v.end(), 3);

🎉insert() 在position之前插入val

(1)在指定位置前插入一个val,并返回指向新插入元素的迭代器。

	vector<int> v = { 1, 2 , 3 , 5 };
	auto it = v.insert(v.begin() + 3, 4);
	//v={1,2,3,4,5}

(2)在指定位置前插入nval副本。它不返回任何值。

(3)在 [ first , last ) 区间内的元素插入到指定的位置前。不包括 last ,是一个左闭右开区间。不返回任何值。

	// 使用列表方式初始化,C++11新语法
	vector<int> v{ 1, 2, 3, 4 };

	// 在指定位置前插入值为val的元素,比如:3之前插入30,如果没有则不插入
	// 1. 先使用find查找3所在位置
	// 注意:vector没有提供find方法,如果要查找只能使用STL提供的全局find
	auto pos = find(v.begin(), v.end(), 3);
	if (pos != v.end())
	{
		// 2. 在pos位置之前插入30
		v.insert(pos, 30);
	}

	vector<int>::iterator it = v.begin();
	while (it != v.end()) 
	{
		cout << *it << " ";
		++it;
	}
	cout << endl;

	pos = find(v.begin(), v.end(), 3);
	// 删除pos位置的数据
	v.erase(pos);

	it = v.begin();
	while (it != v.end()) {
		cout << *it << " ";
		++it;
	}
	cout << endl;

🎉erase() 删除position位置的数据

删除指定位置,或者一个迭代器区间。

	vector<int> v1;
	v1.push_back(1);
	v1.push_back(2);
	v1.push_back(3);
	v1.push_back(4);

	v1.erase(v1.begin() + 3);

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

 输出:1 2 3

如若对你有帮助,记得点赞、收藏、关注哦!

若有误,望各位,在评论区留言或者私信我 指点迷津!!!谢谢^ ^ ~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值