C++ STL之vector使用

第三章  STL

vector的介绍

默认成员函数

关于空间的方法

迭代器

正向迭代器

反向迭代器

const迭代器

find和sort

增删改查

迭代器失效

第一种情况

第二种情况

交换和清理


vector的介绍


vector是一个动态增长的数组,使用的是同一块连续的空间,当空间不足就会涉及到空间增容

优点:支持下标的随机访问。

缺点:数据过多时头插和中部插入的效率很低。

默认成员函数

 _start;        // 指向第一个位置
 _finish;        // 指向最后一个的下一个位置
// _finish - _strat = size。
_endofstorage; // 指向开辟空间的最后一个的下一个位置

关于空间的方法


与string的方法名字和功能一样

方法名功能
size获取数据个数
capacity获取容量大小
empty判断是否为空
resize即会改变空间也会改变数据
reserve  开空间,只改变空间(容量)大小

reserve只负责开辟空间,如果知道需要多少空间,reserve可以缓解vector多次增容的代价

resize在空间的同时还会进行初始化,影响size。

不自己手动开空间,在空间不足时。vs下使用的STL基本是按照1.5倍方式扩容。linux下使用的STL基本是按照2倍方式扩容

迭代器


 vector 和 string 的 迭代器 本质上就是原生指针,比较简单,但后续容器的 迭代器 就比较复杂了

正向迭代器

	// 可读可写
    vector<int>::iterator it = v1.begin();
	while (it != v1.end())
	{
		cout << *it << ' ';
		it++;
	}
	cout << endl;

反向迭代器

	// 可读可写
    vector<int>::reverse_iterator rit = v1.rbegin();
	while (rit != v1.rend())
	{
		cout << *rit << ' ';
		rit++;
	}

begin() 和 end() 适用于 正向迭代器

  • begin() 为对象中的首个有效元素地址
  • end() 为对象中最后一个有效元素的下一个地址

rbegin() 和 rend() 适用于 反向迭代器

  • rbegin() 为对象中最后一个有效元素地址
  • rend() 为对象中首个有效元素的上一个地址

不能混用

const迭代器

void print_vector(const vector<int>& v)
{
	vector<int>::const_iterator it = v.begin(); // 因为是const对象
	while (it != v.end())
	{
		cout << *it << ' ';
		it++;
	}
	cout << endl;

	//vector<int>::const_reverse_iterator rit = v.rbegin(); // 反向的

}

 对于 const 对象,还有 cbegin()cend() 和 crbegin()crend(),当然这些都是 C++11 中新增的语法

 对于 const 对象,存在重载版本,如 begin() const,也就是说,const 修饰的对象也能正常使用 begin() 和 end()rbegin() 和 rend()C++11 中的这个新语法完全没必要,可以不用,但不能看不懂

find和sort


vector没有自己的find方法

如果要查找一个指定的值,需要调用算法库中的find。

	vector<int>::iterator pos = find(v1.begin(), v1.end(), 66);

该函数使用 operator== 将各个元素与 val 进行比较。 此函数模板的行为等同于:

template<class InputIterator, class T>
  InputIterator find (InputIterator first, InputIterator last, const T& val)
{
  while (first!=last) {
    if (*first==val) return first;
    ++first;
  }
  return last;
}

 返回值:

        返回指向范围内比较等于 val 的第一个元素的迭代器。 如果没有元素匹配,函数返回最后一个(最后一个并没有值,是一个指针,指向的是一个没有值的空间)。

	// 算法库中排序
	sort(v1.begin(), v1.end()); // 排序  // 默认为升序

增删改查


增删改查功能
push_back尾插
pop_back尾删
insert插在指定的位置处,参数是迭代器
erase删除指定的位置,参数是迭代器
	vector<int> v1;
	v1.push_back(55);
	v1.push_back(2);
	v1.push_back(66);
	v1.push_back(4);
	v1.push_back(10);
	v1.insert(v1.begin(), 2); // 头插
	v1.erase(v1.begin()); // 头删
	v1.erase(v1.begin()+3);
	print_vector(v1); // 55 2 66 10

删除指定的数 

	// vector没有find接口,这是算法库中的
	vector<int>::iterator pos = find(v1.begin(), v1.end(), 66);
	if (pos != v1.end())
	{
		//cout << *pos;
		v1.erase(pos);
	}

迭代器失效


第一种情况

	vector<int>::iterator it = v1.begin();
	v1.push_back(10); // 迭代器的使用过程中不能添加数据
	v1.push_back(10); // 可以理解为因为增容开辟了新空间。原来的地址失效了
	while (it != v1.end())
	{
		cout << *it;
		it++;
	}

第二种情况

vector<int>::iterator it = v1.begin();
	// 要求删除偶数
	while (it != v1.end())
	{
		if (*it % 2 == 0)
		{
			// 删除之后it就失效了,因为it的位置不对了
			//v1.erase(it); // 不能这么写
			it = v1.erase(it);  // erase会返回删除位置的下一个
		}
		else
		{
			it++;
		}
	}
	for (auto& i : v1)
	{
		cout << i <<' ';
	}

交换和清理


vector<int> v1 = { 1,2,3 };
vector<int> v2 = { 4,5,6 };

v1.swap(v2);    //交换两个对象

v1.clear();
v2.clear();    //清空

swap  函数:

  • 这个函数实现原理不同 std::swapstd::swap 实际在交换时,需要调用多次拷贝构造和赋值重载函数,对于深拷贝来说,效率是很低的
  • 而 vector::swap 在交换时,交换是三个成员变量,因为都是指针,所以只需要三次浅拷贝交换,就能完美完成任务
  • 实际在 vector::swap 内部,还是调用了 std::swap,不过此时是高效的浅拷贝
void swap(vector<T>& v)
{
    std::swap(_start, v._start);
    std::swap(_finish, v._finish);
    std::swap(_endofstorage, v._endofstorage);
}

clear 函数:

  • 令 _finish 等于 _start,就完成了清理,不需要进行缩容,这样做是低效的
void clear()
{
    _finish = _start;//不能置空,会发现内存泄漏
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值