C++ Vector总结

Reference:

一.vector 的构造函数形式

  • (1)vector():创建一个空vector

  • (2)vector(int nSize): 创建一个vector,元素个数为nSize,每个值默认初始化为0
    vector(int nSize,const t& t): 创建一个vector,元素个数为nSize,且值均为t

  • (3)vector(begin,end):复制[begin,end)区间内另一个数组的元素到vector中.

  • (4)vector(const vector&):复制构造函数

1、vector( const Allocator& = Allocator() );
2、vector( size_type n,constT& value = T(), const Allocator& = Allocator() );
3、template vector ( InputIterator first, InputIterator last, const Allocator& = Allocator() );
4、vector ( const vector<T,Allocator>& x );

除了第4个构造函数,其他的几个构造函数都有一个缺省参数Allocator,它是用于指定要使用的空间配置器的,STL提供的默认的空间配置器,我们基本不用管这个参数,除非是我们自己实现了一个空间配置器,然后希望使用我们自己写的空间配置器。
各个构造函数的使用:

  • Ⅰ.vector( size_type n,constT& value = T(), const Allocator& = Allocator() );
    在这里插入图片描述

  • Ⅱ.vector()
    在这里插入图片描述

  • Ⅲ.vector(begin,end)
    在这里插入图片描述

  • Ⅳ. vector ( const vector<T,Allocator>& x );
    拷贝构造函数,根据一个vector对象构建一个新的vector对象
    注意,拷贝有深拷贝和浅拷贝两种方式。 一般在创建一个新的对象时使用的就是深拷贝,即元素值相同,地址空间不同,而在使用一个vector对象进行值传递传参时,使用的就是浅拷贝,即形参是实参的一份临时拷贝。这往往是会出问题的,所以建议在使用vector作为参数时,尽量传引用。

在这里插入图片描述

#include <vector>
#include <iostream>
using namespace std;
 
int main()				
{	
	vector<int>::iterator v1_iter,v2_iter,v3_iter,v4_iter;
	//创建一个长度为3,初始值为0的int型向量--------------------------
	vector<int> v1(3);
	cout<<"v1 = :";
	for(v1_iter = v1.begin(); v1_iter != v1.end();v1_iter ++)
		cout<<" "<<*v1_iter;
	cout<<endl;
 
	//创建一个长度为5,初始值为2的int型向量---------------------------------
	vector<int> v2(5,2);
	cout<<"v2 = :";
	for(v2_iter = v2.begin(); v2_iter != v2.end();v2_iter ++)
		cout<<" "<<*v2_iter;
	cout<<endl;
 
	//创建一个int型向量,并用v2初始化它--------------===----------------------
	vector<int> v3(v2);
	cout<<"v3 = :";
	for(v1_iter = v3.begin(); v1_iter != v3.end();v1_iter ++)
		cout<<" "<<*v1_iter;
	cout<<endl;
 
	//创建一个nt型向量,并用v2部分元素初始化它------------------------------------
	vector<int> v4(v2.begin()+1,v2.begin()+3);
	cout<<"v4 = :";
	for(v4_iter = v4.begin(); v4_iter != v4.end();v4_iter ++)
		cout<<" "<<*v4_iter;
	cout<<endl;
 
	system("pause");			
	return 0;			
}				

在这里插入图片描述

二. vector的大小和容量

vector的reserve和resize

vector<T> ::size_type  size() const:返回向量中元素的个数
vector<T> ::size_type  capacity() const:返回当前向量张红所能容纳的最大元素值
vector<T> ::size_type  max_size() const:返回最大可允许的vector元素数量值

容器对象调用**size()**可以知道当前容器里面有多少个元素,对vector向量对象来说,就是当前存放的元素的个数。

容器对象调用**capacity()**函数,可以知道容器的大小,也就是当前容器对象可用容纳的元素个数。Capacity随着向量的元素的增加而增加,当size() ==capacity()时,容器会自动重新alloc内存,增加一倍的内存。
在这里插入图片描述
当创建空容器时, 容量(capacity)为 0;当用完时,增加原容量的 1/2 (各编译器 可能存在差异 vs2013是这样的,mingw则 增加原容量 )–适用如 vector这种 元素连续存储的容器, 如为list则不同。
capacity 一般大于size的原因是为了避免 每次增加数据时都要重新分配内存,所以一般会 生成一个较大的空间,以便随后的数据插入。

C++ vector的reserve和resize详解

vector 的reserve增加了vector的capacity,但是它的size没有改变!而resize改变了vector的capacity同时也增加了它的size!
原因如下:
reserve是容器预留空间,但在空间内不真正创建元素对象,所以在没有添加新的对象之前,不能引用容器内的元素。加入新的元素时,要调用push_back()/insert()函数。

  resize是改变容器的大小,且在创建对象,因此,调用这个函数之后,就可以引用容器内的对象了,因此当加入新的元素时,用operator[]操作符,或者用迭代器来引用元素对象。此时再调用push_back()函数,是加在这个新的空间后面的。

两个函数的参数形式也有区别的,reserve函数之后一个参数,即需要预留的容器的空间;resize函数可以有两个参数,第一个参数是容器新的大小,第二个参数是要加入容器中的新元素,如果这个参数被省略,那么就调用元素对象的默认构造函数。下面是这两个函数使用例子:

三. vetor 对象上的操作

在这里插入图片描述
在这里插入图片描述

1.插入元素:push_back()

(1)**push_back()**添加到末尾

void push_back (const value_type& val);

 a.push_back( val);  //a是vector向量

如果vector的容器已满,在末尾添加元素时会alloc申请更大的内存,并拷贝之前的元素到新内存,再把元素添加到vector容器末尾

(2)insert()插入一个元素

1) insert (iterator position, const value_type& val)

传入的参数是迭代器的位置和需要插入的元素val。
Position可以是a.begin(),也可以是a.end(),或者这两者中间的一个迭代器位置

2)void insert (iterator position, size_type n, const value_type& val);

在position位置开始,插入n个值为val的元素

3)void insert (iterator position, InputIterator first, InputIterator last);

在position位置插入first(比如数组首地址)到last(比如数组首地址+n)之间的元素。

最常用的是insert (iterator position, const value_type& val);

总结

insert() 函数有以下三种用法:
1、在指定位置loc前插入值为val的元素,返回指向这个元素的迭代器
2、在指定位置loc前插入num个值为val的元素
3、在指定位置loc前插入区间[start, end)的所有元素

//创建一个vector,置入字母表的前十个字符 
vector <char> Avector; 
for( int i=0; i < 10; i++ ) 
  Avector.push_back( i + 65 ); 
 
 
//插入四个C到vector中 
vector <char>::iterator theIterator = Avector.begin(); 
Avector.insert( theIterator, 4, 'C' ); 
 
 
//显示vector的内容 
for( theIterator = Avector.begin(); theIterator != Avector.end(); theIterator++ ) 
  cout < < *theIterator; 

2.查找:find()

调用find方法(需要include)

template <class InputIterator, class T>

   InputIterator find (InputIterator first, InputIterator last, const T& val)
//如查找元素为value,找到则返回迭代器的位置,否则迭代器将指向end()

std::vector <  Type >:: iterator   iVector;

iVector = std::find(a.begin(), a.end() , value);

if(  iVector  !=  a.end()){

	找到了
}

else{

	没找到

}

3.删除末尾元素或者删除全部元素:pop_back()/erase()/clear()

iterator erase(iterator it):删除向量中迭代器指向元素
iterator erase(iterator first,iterator last):删除向量中[first,last)中元素
void pop_back():删除向量中最后一个元素
void clear():清空向量中所有元素

(1)删除一个末尾元素

a.pop_back();

//删除操作避免大量移动的方法,如果元素有申请堆栈的内存,需要换另外一种方法删除,因为需要先获取元素,释放元素指向的申请内存后,才能做删除操作,不然会造成内存泄漏。

(2)删除全部元素

while(pVector->size() != 0)

{

//pop_back方法无返回值

pVector->pop_back();

//删除操作避免大量移动的方法,如果元素有申请堆栈的内存,不可用此方法

}

(3)调用clear函数删除全部元素

a.clear()

(4)另外一种删除全部元素的方法:erase()

//这种方法针对元素有另外申请内存的情况下比较有用,比如元素是一个结构体或者对象,有成员p申请了堆内存,删除元素前要释放内存。

VectorT::iterator iVector = a.begin();

while(iVector != a.end())

{

delete (*iVector)->p;

iVector = a.erase(iVector);

//执行erase后,iVector将指向删除的元素的下一个元素

}

(5).删除一个不一定是末尾的元素

//先执行find查找value的值,在vector容器里面就删除

VectorType::iterator iVector = std::find(a.begin(),  a.end(), value);

if(iVector != a.end()){

a.erase(iVector); //参数只能是迭代器
//std::cout<<" erase success "<< m<<std::endl;

}

4.遍历

reference at(int pos):返回pos位置元素的引用
reference front():返回首元素的引用
reference back():返回尾元素的引用
iterator begin():返回向量头指针,指向第一个元素
iterator end():返回向量尾指针,指向向量最后一个元素的下一个位置
reverse_iterator rbegin():反向迭代器,指向最后一个元素
reverse_iterator rend():反向迭代器,指向第一个元素之前的位置
//利用迭代器,一开始迭代器iVector指向begin,只要不等于end,就继续遍历下去

typedef std::vector <  Type >  VectorT;

VectorT a;

VectorT::iterator iVector = a.begin();  

while(iVector != a.end()){   

 std::cout<<" dump "<< (*iVector)<<std::endl;

 ++iVector;  

}  

5.排序:sort()

std::sort( a.begin() , a.end() );

也可以是

 std::sort( a.begin() , a.begin() + 4 );

反正就是传入排序的位置范围。默认是升序

另外可以实现自己的排序函数Compare comp

 void sort (RandomAccessIterator first, RandomAccessIterator last, Compare comp);

6.判断函数:empty()

bool empty() const:判断向量是否为空,若为空,则向量中无元素

7.反向迭代器(rbegin,rend)

c.begin() 返回一个迭代器,它指向容器c的第一个元素

c.end() 返回一个迭代器,它指向容器c的最后一个元素的下一个位置

c.rbegin() 返回一个逆序迭代器,它指向容器c的最后一个元素

c.rend() 返回一个逆序迭代器,它指向容器c的第一个元素前面的位置

上述每个操作都有两个不同的版本:一个是const成员,另一个是非const成员。这些操作返回什么类型取决于容器是否为const。如果容器不是const,则这些操作返回iterator或reverse_iterator类型。如果容器是const,则其返回类型要加上const_前缀,也就是const_iterator和const_reverse_iterator类型。

8.:assign()

函数原型:

void assign(const_iterator first,const_iterator last);

void assign(size_type n,const T& x = T());

功能:

将区间[first,last)的元素赋值到当前的vector容器中,或者赋n个值为x的元素到vector容器中,这个容器会清除掉vector容器中以前的内容。

举例

#include <vector>
#include <iostream>

int main( )
{
	using namespace std;
	vector<int> v1, v2, v3;
	vector<int>::iterator iter;
	
	v1.push_back(10);
	v1.push_back(20);
	v1.push_back(30);
	v1.push_back(40);
	v1.push_back(50);
	v2.push_back(1);
	v2.push_back(2);
	
	cout << "v1 = " ;
	for (iter = v1.begin(); iter != v1.end(); iter++)
	cout << *iter << " ";
	cout << endl;
	
	cout << "v2 = ";
	for (iter = v2.begin(); iter != v2.end(); iter++)
		cout << *iter << " ";
	cout << endl;
	
	v2 = v1;
	cout << "v2 = ";
	for (iter = v2.begin(); iter != v2.end(); iter++)
		cout << *iter << " ";
	cout << endl;
	
	v2.assign(v1.begin(), v1.end());
	cout << "v2 = ";
	for (iter = v2.begin(); iter != v2.end(); iter++)
		cout << *iter << " ";
	cout << endl;
	
	v3.assign(7, 3) ;
	cout << "v3 = ";
	for (iter = v3.begin(); iter != v3.end(); iter++)
		cout << *iter << " ";
	cout << endl;
	
	return 0;
	}

四.vector 操作总结

(1)a.assign(b.begin(), b.begin()+3);//b为向量,将b的0~2个元素构成的向量赋给a
(2)a.assign(4,2);//是a只含4个元素,且每个元素为2
(3)a.back();//返回a的最后一个元素
(4)a.front();//返回a的第一个元素
(5)a[i]; //返回a的第i个元素,当且仅当a[i]存在2013-12-07
(6)a.clear();//清空a中的元素
(7)a.empty();//判断a是否为空,空则返回ture,不空则返回false
(8)a.pop_back();//删除a向量的最后一个元素
(9)a.erase(a.begin()+1,a.begin()+3);//删除a中第1个(从第0个算起)到第2个元素,也就是说删除的元素从a.begin()+1算起(包括它)一直到a.begin()+3(不包括它)
(10)a.push_back(5);//在a的最后一个向量后插入一个元素,其值为5
(11)a.insert(a.begin()+1,5);//在a的第1个元素(从第0个算起)的位置插入数值5,如a为1,2,3,4,插入元素后为1,5,2,3,4
(12)a.insert(a.begin()+1,3,5);//在a的第1个元素(从第0个算起)的位置插入3个数,其值都为5
(13)a.insert(a.begin()+1,b+3,b+6);//b为数组,在a的第1个元素(从第0个算起)的位置插入b的第3个元素到第5个元素(不包括b+6),如b为1,2,3,4,5,9,8,插入元素后为1,4,5,9,2,3,4,5,9,8
(14)a.size();//返回a中元素的个数;
(15)a.capacity();//返回a在内存中总共可以容纳的元素个数
(16)a.rezize(10);//将a的现有元素个数调至10个,多则删,少则补,其值随机
(17)a.rezize(10,2);//将a的现有元素个数调至10个,多则删,少则补,其值为2
(18)a.reserve(100);//将a的容量(capacity)扩充至100,也就是说现在测试a.capacity();的时候返回值是100.这种操作只有在需要给a添加大量数据的时候才 显得有意义,因为这将避免内存多次容量扩充操作(当a的容量不足时电脑会自动扩容,当然这必然降低性能) 
(19)a.swap(b);//b为向量,将a中的元素和b中的元素进行整体性交换
(20)a==b; //b为向量,向量的比较操作还有!=,>=,<=,>,<

五.几种重要的算法

使用时需要包含头文件:

#include <algorithm>
(1)sort(a.begin(),a.end()); 
//对a中的从a.begin()(包括它)到a.end()(不包括它)的元素进行从小到大排列

(2)reverse(a.begin(),a.end());
 //对a中的从a.begin()(包括它)到a.end()(不包括它)的元素倒置,但不排列,如a中元素为1,3,2,4,倒置后为4,2,3,1
 
(3)copy(a.begin(),a.end(),b.begin()+1);
 //把a中的从a.begin()(包括它)到a.end()(不包括它)的元素复制到b中,从b.begin()+1的位置(包括它)开始复制,覆盖掉原有元素

(4)find(a.begin(),a.end(),10);
 //在a中的从a.begin()(包括它)到a.end()(不包括它)的元素中查找10,若存在返回其在向量中的位置

六.选用vector与 deque

c++STL vector扩容过程

  • Vector:

动态数组,内存中一整块连续区域。支持.reserve()和.capacity()。为提高效率,最好在添加元素之前用.reserve()分配好容量。插入删除操作越靠近数组首部效率越低。

  • deque(double ended queue):

动态数组,内存中多段连续区域拼凑。不支持reserve()和capacity()函数。首尾插入删除操作相对效率高。

总结:

vector和deque都是动态数组类型的,都可通过[]访问。一般选择vector, 但当需要从首尾两端进行插入或删除元素操作时,应该选择deque.

七.二维vector初始化

//二维vector初始化
    vector< vector<int> > vt;//初始化一个 二维vector
    vector<vector<int> > vect(vt);//使用另一个 二维 vector 初始化当前二维vector
    vector< vector<int> > vec(row,vector<int>(column));//初始化一个 二维的vector 行row,列column,且值为0
    vector<vector<int> > visited(row,vector<int>(column,6));//初始化一个 二维vector 行row,列column ,且 值为data=6 自定义data;
    vector<vector<int> > vecto(row,vector<int>(vt[0].begin()+1,vt[0].begin()+3));初始化一个 二维vector 行row,第二个参数为一维vector;

笔试总结,编程题7,如何初始化二维数组,输入的写法

八. C++数组初始化

参考:C++数组初始化方法

定义

int *pia = new int[10];此 new 表达式分配了一个含有 10 个 int 型元素的数组,并返回指向该数组第一个元素的指针,此返回值初始化了指针 pia。
typedef int arrT[10]; //arrT表示10个int的数组类型
int *pi1 = new arrT; //10个未初始化的int
int *pi2 = new arrT(); //10个初始化为0的int
int *pi3 = new arrT{0,1,2,3,4,5,6,7,8,9}; //VS2010不支持

在自由存储区中创建的数组对象是没有名字的,只能通过其地址间接地访问堆中的对象。

注意:C++使用new和delete在堆(自由存储区)上分配和释放动态数组

动态数组初始化

  1. 元素只能初始化为元素类型的默认值,而不能像数组变量一样,用初始化列表为数组元素提供各不相同的初值。

  2. 对于内置数据类型元素的数组,必须使用()来显示指定程序执行初始化操作,否则程序不执行初始化操作:

int *pia = new int[10]; // 每个元素都没有初始化
 
int *pia2 = new int[10] ();  // 每个元素初始化为0,括号内不能写其他值,只能初始化为0

3.类类型元素的数组,则无论是否使用(),都会自动调用其默认构造函数来初始化:

string *psa = new string[10];  // 每个元素调用默认构造函数初始化
 
string *psa = new string[10]();  // 每个元素调用默认构造函数初始化

动态分配空数组

char *cp = new char[0];之后,可以动态改变cp的维数。

动态释放

delete [] pia;

示例

const char *pc = "a very long literal string"; // 处理C风格字符串时使用const指针
 
const size_t len = strlen(pc) +1;      // size_t用于数组的大小和下标
 
for (size_t ix = 0; ix != 1000000; ++ix) {
 
    char *pc2 = new char[len]; // pc2指向的存储空间的内容会动态改变,因此不使用const
 
    strncpy (pc2, pc, len); // 使用strncpy比使用strcpy安全
 
    // do something;
 
    delete [] pc2;
 
}

九.范围for循环

在这里插入图片描述

vector<int> v(10, 2);
for (auto &r : v) {
    r *= 2;
}

==============================================>>>>>>>>>>>>>

for (auto beg = v.begin(), end = v.end(); beg != end; ++beg) {
    auto &r = *beg;
    r *= 2;
}

在这里插入图片描述

在这里插入图片描述

  • 4
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
引用:在C++的标准模板库(STL)中,vector是一种动态数组容器。它提供了一组构造函数,用于创建不同类型和大小的vector对象。 引用:vector容器的使用方法是通过包含头文件<vector>来引入vector类。可以使用不同的构造函数来创建vector对象,如空的vector、指定大小的vector、使用其他vector来初始化的vector等。 引用:在vector容器中,可以使用[]运算符来获取元素,且vector和deque都支持这种操作。一般情况下,vector更适合在中间插入和删除元素,而deque更适合在首尾两端进行插入和删除元素操作。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *3* [C++ Vector总结](https://blog.csdn.net/weixin_43892514/article/details/104233686)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *2* [C++ vector用法详解](https://blog.csdn.net/zhanghaijun2013/article/details/105657663)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值