c++ stl容器 vector详解

一、简介
     顺序容器是拥有单一类型的一个有序集合,vector ,list(双向链表),queue(队列);
     关联容器支持查询一个元素是否存在,也就是对元素进行排序的容器,map(映射),set(集合)。map 每个元素拥有两个数据,一个是索引,一个是值,而set只相当于一个排序后的集合。

二、vector
     vector是一个顺序容器,相当于一个动态数组。因为vector中元素是连续存储的,所以除了迭代器也可以使用指针偏移来访问,也就是说vector的任意元素可以通过指针和偏移量传递给其他函数。
     vector是自动申请或释放存储空间的。vector占用的空间通常比实际需要的更大,因为这样就不必每次修改时都重新申请空间。可以通过capacity()函数来查询总共占用的空间,额外的空间也可以通过shrink_to_fit()函数来释放
     重新分配空间需要话费一些代价,如果事先知道元素数量的花可以使用reserve()函数来避免重新分配空间。
2.1 时间复杂度
  •      随机访问 O(1)
  •      在末尾删除或者插入元素 O(1)
  •      擦除元素,插入元素 O(n),具体是插入位置和end()直接的距离
2.2 定义
     
template<

    class T,
    class Allocator = std::allocator<T>

> class vector;
  • T 元素类型
  • Allocator 用来申请空间存储元素,一般不用
2.3 特殊情况

vector<bool>  经过专门优化,以bit为单位,可以有效节省空间

2.4 迭代器失效
     迭代器在什么情况下会失效呢,在我的理解,一是元素被释放,二是重新分配空间
操作迭代器
所有读操作和swap函数不会失效
reserve,shrink_to_fit,clear_,operator =等重新分配空间的情况实效
erase擦除元素被擦除的元素和其之后的元素都会失效,包括.end()
push_back,emplace_back若重新分配,都失效,否则,只有end()失效
insert,emplace,resize若重新分配,都失效,否则,所有在其之后的节点,失效
pop_back被pop的元素和end()失效

2.5 成员变量
value_typeT
allocator_typeAllocator
size_typesize,无符号整数
difference_type有符号整数类型?
reference引用 Allocator::const_reference
const_referenceconst引用
pointer 
const_pointer 
iterator迭代器
const_iteratorconst迭代器
reverse_iterator反向迭代器
const_reverse_iteratorconst~

2.6 成员函数

2.6.1 构造函数
explicit vector( const Allocator& alloc = Allocator() );            (1)(until C++14)
vector() : vector( Allocator() ) {}
explicit vector( const Allocator& alloc );
(since C++14)
  (2)  
explicit vector( size_type count, 

                 const T& value = T(),

                 const Allocator& alloc = Allocator());
(until C++11)
         vector( size_type count, 

                 const T& value,

                 const Allocator& alloc = Allocator());
(since C++11)
  (3)  
explicit vector( size_type count );(since C++11)
(until C++14)
explicit vector( size_type count, const Allocator& alloc = Allocator() ); (since C++14)
template< class InputIt >

vector( InputIt first, InputIt last, 

        const Allocator& alloc = Allocator() );
(4)  
vector( const vector& other ); (5)  
vector( const vector& other, const Allocator& alloc ); (5) (since C++11)
vector( vector&& other ) (6) (since C++11)
vector( vector&& other, const Allocator& alloc ); (6) (since C++11)
vector( std::initializer_list<T]]> init, 
        const Allocator& alloc = Allocator() );
(7) (since C++11)
1) 默认构造函数,构造一个空的容器
2) 构造函数,提供元素数量和初始值
3)值提供元素数量
4)提供一个范围,比如另一个容器的begin(),end();
5)   拷贝构造函数,提供另一个容器
6)移动构造函数,提供另一个容器.移动构造函数的参数是“右值引用&&”,是临时变量,占用临时变量的空间来提高性能, http://www.cnblogs.com/hujian/archive/2012/02/13/2348621.html
7)用一些元素来初始化容器
#include <iostream>
#include <vector>
#include <iterator>
using namespace std;
void printV(vector<int> &num){
     vector<int>::iterator it;
     for(it=num.begin();it!=num.end();it++){
          cout<<*it<<" ";
     }
     cout<<endl;
    
}
int main(){
     //constructor
     vector<int> num1;
     cout<<"num1: ";
     printV(num1);
     vector<int> num2(5,9);
     cout<<"num2: ";
     printV(num2);
     vector<int> num3(4);
     cout<<"num3: ";
     printV(num3);
     vector<int> num4(num1.begin(),num1.end());
     cout<<"num4: ";
     printV(num4);
     // vector<int> num7={1,2,3,4,5,6,7,8,9};c++11中支持
     // cout<<"num7: ";
     // printV(num7);
     vector<int>     num5(num2);
     cout<<"num5: ";
     printV(num5);
     cout<<"num2 after copy constructor: ";
     printV(num2);
     vector<int> num6(num2);
     cout<<"num6: ";
     printV(num6);
     cout<<"num2 after move constructor: ";
     printV(num2);
     int x[5]={1,2,3,4,5};
     vector<int> num8(x,x+5);
     cout<<"num8 range constructor4 by array: ";
     printV(num8);


}     



2.6.2 赋值操作 operator =
vector& operator=( const vector& other ); (1)  
vector& operator=( vector&& other ); (2) (since C++11)
vector& operator=( std::initializer_list<T]]> ilist ); (3) (since C++11)
     
三种,分别是拷贝赋值函数,移动赋值函数,初始化列表赋值,与构造函数基本相同。

2.6.3 获取分配器类型 //?
     get_allocator

2.6.4 访问元素
  •      at:返回一个引用,若pos超过size(),会返回一个一异常
  • operator[] :返回一个引用,但是不会检查是否越界
  • front:返回第一个元素的引用,但是对于空容器结果是不确定的
  • back:返回最后一个元素的引用,对于空容器结果也是不确定的
  • data:c++11,对于非空容器,返回的是&front()//?
2.6.5 获取迭代器
  • begin/cbegin
  • end/cend
  • rbegin/crbegin
  • rend/crend
     begin都是指向第一个值(正向或反向),end都是指向最后一个值的下一个空值

2.6.6 容量Capacity
  • empty:检查是否为空
  • size:返回元素的数目
  • max_size:最大可能的元素数目,通常为很大很大的数,是容器能够达到的极限
  • reverse:参数为新容量,返回值为void
  • capacity:已分配最大空间数目(单位是元素)
  • shrink_to_fit:重新分配空间,使空间刚刚合适
2.6.7 修改元素
  • clear:清空容器,无返回值
  • insert:添加元素,返回新添加第一个元素的迭代器
  1. 参数为迭代器,值,在该迭代器之前插入一个值
  2. 参数为迭代器,count,value,在该迭代器之前添加多个值
  3. 参数为迭代器,first,last,在该迭代器之前,添加[first,last)的值
  4. 参数迭代器,初始化列表(initializer_list<T> ilist, 在该迭代期之前添加ilist(C11)
  • emplace:与insert有所区别,暂不解释//?
  • erase:擦除元素,返回被擦除最后一个元素的下一个迭代器
  1. 参数为迭代器,删除该迭代器指向的元素
  2. 参数为迭代器first,迭代器last,删除[first,last)的内容,前闭后开
  • push_back 返回值为void
    • 在容器的最后添加元素,也分拷贝和移动两种,参考构造函数
  • emplace_back 暂不解释
  • pop_back() 返回值为void
  • resize 调整元素的数量,返回值为 void
    1. 参数为count
    2. 参数为count,value
    • 若count小于当前size,则相当于做size-count次pop操作
    • 若count大于当前size,则多出来的用value补齐
  • swap:参数为容器引用,交换两个容器的值,迭代器都还有效
2.7 非成员函数
       分别按索引比较,比如lhs[i]<rhs[i],for all i,则lhs<rhs;编译时发现除了==,!=,只要第一个元素符合,就会符合,不知道到底是怎样,先放在这里。//?
  • == 如果两个容器的所有元素都相等,返回true,size也必须相同
  • !=   与==相反
  • <     如果等式左边的元素们按字典顺序小于右边等式的元素们,返回true
  • <=
  • >
  • >=
  • swap     交换两个容器的元素,size不必相等
三、疑问
  1. emplace系列函数
  2. 移动构造,移动赋值,右值引用
  3. <=,<,>=,>
  4. 和数组差不多,假设删除一个元素后将后面的元素顺序前移动,为什么被erase的iterator失效
#include <iostream>
#include <vector>
#include <iterator>
using namespace std;
//iterator
void printV(vector<int> &num){
	vector<int>::iterator it;
		
	for(it=num.begin();it!=num.end();it++){
		
		cout<<*it<<" ";
		
	}

	cout<<endl;
	
}
//reverse_iterator
void r_printV(vector<int> &num){
	vector<int>::reverse_iterator it;
	for(it=num.rbegin();it!=num.rend();it++){
		cout<<*it<<" ";
	}
	cout<<endl;
	
}
int main(){
	//constructor
	vector<int> num1;
	cout<<"num1: ";
	printV(num1);
	vector<int> num2(5,9);
	cout<<"num2: ";
	printV(num2);
	vector<int> num3(4);
	cout<<"num3: ";
	printV(num3);
	vector<int> num4(num1.begin(),num1.end());
	cout<<"num4: ";
	printV(num4);
	// vector<int> num7={1,2,3,4,5,6,7,8,9};c++11中支持
	// cout<<"num7: ";
	// printV(num7);
	vector<int>	num5(num2);
	cout<<"num5: ";
	printV(num5);
	cout<<"num2 after copy constructor: ";
	printV(num2);
	vector<int> num6(num2);
	cout<<"num6: ";
	printV(num6);
	cout<<"num2 after move constructor: ";
	printV(num2);
	int x[5]={1,2,3,4,5};
	vector<int> num8(x,x+5);
	cout<<"num8 range constructor4 by array: ";
	printV(num8);
	
	//element access
	int& xByAt=num8.at(3);
	xByAt=13;
	printV(num8);
	//cout<<"exception "<<endl;
	//cout<<num8.at(10)<<endl;

	//capacity
	cout<<"size:"<<num8.size()<<endl;
	cout<<"max_size:"<<num8.max_size()<<endl;
	cout<<"capacity:"<<num8.capacity()<<endl;
	
	vector<int>::iterator it;
	int x1[3]={33,33,33};
	it=num8.begin();
	//insert
	it=num8.insert(it,11);
	it=num8.insert(it,2,22);
	it=num8.insert(it,x1,x1+3);
	cout<<"num8 after insert: ";
	printV(num8);

	//non-member function
	int y[5]={1,9,3,5};
	int z[4]={2,9,3,5};
	vector<int> num9(y,y+4);
	vector<int> num10(z,z+4);
	cout<<"<:"<<(num9<num10)<<endl;
	//swap
	cout<<"num9: ";
	printV(num9);
	cout<<"num10: ";
	printV(num10);
	cout<<"after swap:"<<endl;
	swap(num9,num10);
	cout<<"num9: ";
	printV(num9);
	cout<<"num10: ";
	printV(num10);
	// cout<<"before erase, begin():"<<int(num9.begin())<<endl;
	// num9.erase(num9.begin());
	// cout<<num9.capacity()<<endl;
	// cout<<"after erase, begin():"<<int(num9.begin())<<endl;




}	


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值