C++ vector容器

Vector详解

  • 一、基本概念
  • 二、成员变量
  • 三、重要接口
    • 3.1 构造函数
    • 3.2 iterator
    • 3.3 容量和大小
    • 3.4 增删查改
  • 四、迭代器失效

一、基本概念

  1. vector是表示可变大小的数组的容器
  2. vector是连续存储空间来存储元素的,并且是动态的(如果需要扩容/缩容的话,不是在原来空间的后面增加空间,而是找另一块空间,将原来空间的内容拷贝回去,释放原来的空间)
  3. vector容器在头文件 < vector >中

二、成员变量

vector是用三个指针来维护的

start:指向空间的开头
finish:指向有效数据的尾
endOfStorage:指向存储空间的尾

C++ vector容器_第1张图片

三、重要接口

3.1 构造函数

默认构造 vector ()
构造并初始化n个value vector(n,value)
拷贝构造 vector(const vector& v)
迭代器区间构造 vector(InputIterator first,InputIterator last)

代码演示

void printVector(vector<int>& v)
{	//利用迭代器打印 v
	for (vector<int>::iterator it = v.begin(); it != v.end(); ++it)
	{
		cout << *it << " ";
	}
	cout << endl;
}

int main()
{
	vector<int> v; //默认构造
	vector<int> v1(10, 1);  //构造10个1
	vector<int> v2(v1.begin(), v1.end());  //利用v1的迭代器区间构造
	vector<int> v3(v2);  //拷贝构造
	printVector(v);
	printVector(v1);
	printVector(v2);
	printVector(v3);
	return 0;
}

在这里插入图片描述

3.2 iterator

vector的iterator可以简单的理解成指针。

begin() 返回第一个数据位置的iterator
end() 返回最后一个数据位置的后一个 的iterator
rbegin() 返回最后一个数据位置的iterator
rend() 返回第一个数据位置的前一个的iterator
void PrintVector(const vector<int>& v)
{
	// const对象使用const迭代器进行遍历打印
	vector<int>::const_iterator it = v.begin();
	while (it != v.end())
	{
		cout << *it << " ";
		++it;
	}
	cout << endl;
}

void main()
{
	// 使用push_back插入4个数据
	vector<int> v;
	v.push_back(1);
	v.push_back(2);
	v.push_back(3);
	v.push_back(4);

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

	// 使用迭代器进行修改
	it = v.begin();
	while (it != v.end())
	{
		*it *= 2;
		++it;
	}

	// 使用反向迭代器进行遍历再打印
	// vector::reverse_iterator rit = v.rbegin();
	auto rit = v.rbegin();
	while (rit != v.rend())
	{
		cout << *rit << " ";
		++rit;
	}
	cout << endl;

	PrintVector(v);
}

在这里插入图片描述

3.3 容量和大小

size 返回数据元素的个数
capacity 返回容量的大小
empty 返回是否为空
resize(n) 改变容器的size
reserve(n) 改变容器的capacity

注:

  1. resize第二个参数是缺省参数,如果没传,就默认调用构造函数
  2. 如果resize的n大于size的大小,那么后面的位置会填充你传的数据,如果没传就填充默认数据
  3. 如果resize的n小于size的大小,发生截断
  4. reserve扩容规则在不同编译器下是不同的,vs下capacity是按1.5倍增长的,g++是按2倍增长的

代码演示

int main()
{
	vector<int> v;

	// set some initial content:
	for (int i = 1; i < 10; i++)
		v.push_back(i);

	v.resize(5);
	v.resize(8, 100);
	v.resize(12);

	cout << "v contains:";
	for (size_t i = 0; i < v.size(); i++)
		cout << ' ' << v[i];
	cout << '\n';
	return 0;
}

在这里插入图片描述

3.4 增删查改

push_back(num) 尾插数据
pop_back() 尾删数据
insert(pos,num) 在pos位置前插入数据
insert(pos,size,num) 在pos位置前插入size个数据
erase(pos) 删除pos位置的数据
erase (begin,end) 删除begin~end区间的数据
clear() 清理所有数据
operator[ ] 像数组一样访问数据
int main()
{

	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;

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

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

在这里插入图片描述

四、迭代器失效

迭代器失效的本质就是指向了一块已经被释放的空间(野指针),那什么情况会导致这个问题呢?很明显就是在扩容和缩容的时候,一些接口比如:resize、reserve、insert、assign、push_back都会导致底层空间的改变,导致迭代器失效。
代码演示

int main()
{
	int a[] = { 1, 2, 3, 4 };
	vector<int> v(a, a + sizeof(a) / sizeof(int));
	
	// 使用find查找3所在位置的iterator
	vector<int>::iterator pos = find(v.begin(), v.end(), 3);
	// 删除pos位置的数据,导致pos迭代器失效。
	v.erase(pos);
	
	cout << *pos << endl; // 此处会导致非法访问
	return 0;
}

erase删除pos位置元素后,pos位置之后的元素会往前搬移,没有导致底层空间的改变,理论上讲迭代器不应该会失效,但是:如果pos刚好是最后一个元素,删完之后pos刚好是end的位置,而end位置是没有元素的,那么pos就失效了。因此删除vector中任意位置上元素时,vs就认为该位置迭代器失效了。

你可能感兴趣的:(c++,开发语言)