【C++】vector 的使用,模拟实现,以及迭代器失效问题。

vector的使用:

http://www.cplusplus.com/reference/vector/vector/?kw=vector

vector空间是如何增长的?

当添加元素时,如果vector空间大小不足,则会动态开辟新的空间,新空间的大小要根据STL版本而定,例如vs下capacity是按1.5倍增长的,g++是按2倍增长的。vs是PJ版本STL,g++是SGI版本STL。开辟完新空间将原空间内容拷贝过来,在新空间的内容末尾添加元素,并释放原空间。无论是1.5倍还是2倍都是根据根据需求而定的, 1.5倍增容的次数更多,效率较低,因为每次增容都是要付出时间代价的。而2倍速的增容可能效率更高一些但是比起1.5倍的增容,相同大小的数据量,可能浪费更多的空间。

vector迭代器失效问题

(1)什么是迭代器?
迭代器(iterator)是一种对象,它能够用来遍历标准模板库容器中的部分或全部元素。它的主要作用就是让算法能够不用关心底层数据结构的情况下,遍历容器的元素。迭代器的底层就是指针,或者是对指针的封装。
(2)什么是迭代器失效?
迭代器失效,实际就是迭代器底层对应指针所指向的空间被销毁了,而使用一块已经被释放的空间,造成的后果是程序崩溃(即如果继续使用已经失效的迭代器,程序可能会崩溃)。
(3)迭代器失效的集中情况:
(一)扩容
所有的可能导致vector扩容的操作,都有可能导致vector的迭代器失效,因为扩容的过程是申请新空间,然后拷贝旧空间的数据,然后释放旧空间。扩容操作后 迭代器却还指向旧地址,迭代器就失效了,迭代器失效后只能对迭代器重新赋值才能使用要不然就会报错。下边程序以push_back(),为例详细讲解什么是迭代器失效。

int main(){
	vector<int>v;
	v.push_back(1);
	v.push_back(2);
	v.push_back(3);
	v.push_back(4);
	v.push_back(5);
	vector<int>::iterator it = v.begin();
	v.push_back(6);
	//v.push_back(7);
	while(it < v.end()){
		cout << *it << ' '; 
		it++;
	}
	cout << endl;
	return 0;
}

如果在vs上运行上述程序会正常的输出1 2 3 4 5 6.但是如果第11行的注释去掉,也就是在push_back(6)后加上push_bakc(7),程序就报错了。原因是插入6后vector容器已经满了, 在插入7的时候就会扩容,程序会开辟新的空间并将原有的数据123456拷贝到新的空间,并且将原来的空间释放掉。也就是说当push_back(7)后,it指向的空间已经被释放掉了,所以*it肯定会报错。所以我们在使用例如push_back,insert(),resize().reserve()等会扩容的接口时一定要注意,因为他们可能导致迭代器失效。
(二)删除
erase删除pos位置元素后,pos位置之后的元素会往前搬移,没有导致底层空间的改变,理论上讲迭代器不应该会失效,但是:如果pos刚好是最后一个元素,删完之后pos刚好是end的位置,而end位置是
没有元素的,那么pos就失效了。因此删除vector中任意位置上元素pos时,vs就认为pos 以及 pos后边的迭代器都失效了,例如如下代码:。

int main(){
	vector<int> num{1,2,3,4,5,6,7,8,9,10};
	vector<int>::iterator it1 = num.begin() + 4; 
	vector<int>::iterator it2 = num.begin() + 5;
	vector<int>::iterator it3 = num.begin() + 6;
	num.erase(it2);
	cout << *it1 << endl;
	cout << *it3 << endl;
	return 0;
}

cout << *it1 << endl; 不会报错(it1在pos前,所以不失效)
cout << *it3 << endl; 会报错(it3在pos后,所以失效)
(三)swap
swap也有可能导致迭代器失效例如如下程序。

int main(){
	vector<int> num1{1,2,3,4,5,6,7,8,9,10};
	vector<int> num2{ 1, 2, 3, 4, 5 };
	vector<int>::iterator it = num2.begin(); 
	swap(num1, num2);
	while (it != num2.end()){
		cout << *it ;
		it++;
	}
	
	return 0;
}

vector的模拟实现:

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值