vector

由数组到vector

要素注释
与数组一样的地方vector是采用连续存储空间来存储元素的序列式容器。也就是意味着可以采用下标对vector的元素进行访问,和数组一样高效。
与数组不一样的地方vector的大小是可以动态改变的vector会分配一些额外的空间以适应可能的增长,因为存储空间比实际需要的存储空间更大。
vector分配空间调整不同的库采用不同的策略权衡空间的使用和重新分配。以达到在末尾插入一个元素的时候是在常数时间的复杂度完成的。
vector性能vector占用了更多的存储空间,为了获得管理存储空间的能力,并且以一种有效的方式动态增长。
vector跟其它动态序列容器相比vector在访问元素的时候更加高效(可以通过下标访问),在末尾添加和删除元素相对高效。对于其它不在末尾的删除和插入操作,效率更低。

vector的使用

vector构造函数

构造函数声明释义
vector()无参构造
vector(size_type n,const value_type& value=value_type())构造并初始化前n个元素,第二个参数缺省为0
vector (InputIterator first, InputIterator last)迭代器构造
vector(const vector& x)用vector去拷贝构造

使用数组构造vector更加方便

#include<iostream>
#include<vector>
using namespace std;
int main()
{
	int arr[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
	int len = sizeof(arr) / sizeof(arr[0]);
	vector<int> vec(arr, arr + len);

	for (vector<int>::iterator it = vec.begin(); it != vec.end(); it++)
	{
		cout << *it << endl;
	}
	system("pause");
	return 0;
}

vector iterator 的使用

接口说明
begin()第一个元素的iterator
end()最后一个元素的下一个位置的iterator
rbegin()最后一个元素的iterator
rend()第一个元素的前一个位置的iterator
cbegin()第一个元素的const_iterator
cend()获得最后一个元素的下一个位置的const_iterator

vector的空间增长问题

接口释义
size()或者vector的元素个数
max_size()获取vector的
capacity()获得vector的容量
empty()判断vector是否为空
void resize (size_type n, value_type val = value_type());改变vector的size
void reserve (size_type n);改变vector的capacity

resize()和reserve()函数

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

resize()有点vector重构造的感觉,第二个参数只是“备胎”,这个参数只是给新增有效空间的默认值。如果不给第二个参数,缺省值是0。第一个参数是改造之后的vector的大小,如果第一个参数比原来的size()要小,会丢失数据。
在这里插入图片描述
在这里插入图片描述

reserve(size_type n);

reserve()函数只是改变容量,参数n是修改之后容量的大小。
在这里插入图片描述
reserve的参数小于vector的size(),reserve函数不会造成数据丢失,它只会把capacity置成size。
在这里插入图片描述

  1. vs下capacity是按1.5倍增长的,g++是按2倍增长的。vs是PJ版本STL,g++是SGI版本STL。
  2. reserve只负责开辟空间,如果确定知道需要用多少空间,reserve可以缓解vector增容的代价缺陷问题。
  3. resize在开空间的同时还会进行初始化,影响size。

vector的增删查改

函数接口释义
[ ]像数组一样下标访问
void push_back(const value_type& x);尾插数据x
iterator insert (iterator position, const value_type& val);在pos的iterator位置之前插入x
void pop_back()尾删
iterator erase (iterator pos);删除iterator的pos位置的元素
void swap (vector& x);交换两个vector的数据空间
InputIterator find (InputIterator first, InputIterator last, const T& val);迭代器区间内查找

find函数是算法库的函数,需要加头文件#include <algorithm> // std::find

迭代器失效

insert导致迭代器失效

#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
int main()
{
	int a[] = { 1, 2, 3, 4 };
	vector<int> v(a, a + sizeof(a) / sizeof(int));

	// 在pos位置插入数据,导致pos迭代器失效。
	// insert会导致迭代器失效,是因为insert可
	// 能会导致增容,增容后pos还指向原来的空间,而原来的空间已经释放了。
	vector<int>::iterator it = find(v.begin(), v.end(), 3);
	v.insert(it, 30);
	cout << *it << endl; // 此处会导致非法访问
	system("pause");
	return 0;
}

erase导致迭代器失效

#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
int main()
{
	int a[] = { 1, 2, 3, 4 };
	vector<int> v(a, a + sizeof(a) / sizeof(int));
	
	//删除pos位置的数据,导致pos迭代器失效。
	vector<int>::iterator it = find(v.begin(), v.end(), 3);
	v.erase(it);
	cout << *it << endl;// 此处会导致非法访问

	system("pause");
	return 0;
}

注意

函数原因返回值
insert插入可能会增容,原来的数据空间已经被释放返回插入数据的迭代器
eraseit位置的元素被删,it失效删除数据的下一个元素的迭代器

vector的亲戚

array和vector的比较

不同点:

  1. array是固定大小的线性存储元素。由于其固定大小的特点,不会有空间浪费的问题。
template < class T, size_t N > class array;//定义时候就需要给定大小
  1. array是固定大小的数组,因此array没有push_back、popback、insert、erase、resize、reserve这样改变空间大小的接口,array只能通过下标访问,array就是我们最熟悉的C语言的数组。

  2. array只有max_size()表示容器最多可以容纳的元素个数,没有capacity(),而关于vector的max_size和capacity的区别。
    在这里插入图片描述
    vector的capacity是分配到的空间大小,如果这个vector没有插入数据,那么capacity等于size。一旦vector开始插入数据,随之会有相应的增容。而max_size是vector最大潜在大小,受限制与系统和库。

  3. array有void fill (const value_type& val);可以用来初始化array,Fill array with value。

#include<iostream>
#include<array>
using namespace std;
int main()
{
	array<int, 10> arr;
	arr.fill(10);
	for (size_t i = 0; i < arr.size(); i++)
		cout << arr[i] << endl;
	system("pause");
}
  1. array没有构造函数和析构函数,array在定义时候就开辟了固定空间,vector在构造函数时候才开辟空间。

相同点

  1. 存在插入和删除在非尾部,效率低下,会存在元素的移动,swap效率低下。
  2. array和vector都有front和back这样直接返回首元素和尾元素的引用。at()都会实时监测是否越界,[ ]不会监测,都是返回该位置元素的引用。

柔性数组

C99 中,结构中的最后一个元素允许是未知大小的数组,这就叫做『柔性数组』成员。

typedef struct st_type
{
	int i;
	int a[0]; //柔性数组成员,也可以使用a[]
}type_a;

柔性数组的特点:

  1. 结构中的柔性数组成员前面必须至少一个其他成员。
  2. sizeof 返回的这种结构大小不包括柔性数组的内存。
  3. 包含柔性数组成员的结构用malloc ()函数进行内存的动态分配,并且分配的内存应该大于结构的大小,以适应柔性数组的预期大小。
#include<iostream>
#pragma warning(disable:4200)//使用柔性数组会发出警告,或者将柔性数组元素个数设置为1
using namespace std;

typedef struct st_type
{
	int i;
	int a[0]; //柔性数组成员,或者使用a[]
}type_a;
int main()
{
	int i = 0;
	type_a *p = (type_a*)malloc(sizeof(type_a)+100 * sizeof(int));
	//业务处理
	p->i = 100;
	for (i = 0; i<100; i++)
	{
		p->a[i] = i;
	}

	free(p);
	system("pause");
	return 0;
}

相比结构体中存放一个数组的指针,柔性数组的优势

  1. 增加访问速度,结构体和数组的空间连在一起,访问效率会高一些。
  2. 一次申请空间,一次释放空间。如果采用结构体中存数组的指针的方法,需要分别申请结构体和数组的空间,释放空间也要分两次释放。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值