【STL】C++ vector类模板

基本概念

vector是类型相同的对象的容器,vector的大小可以变化,可以向数组中增加元素。因此,vector容器和数组非常相似,也称为单端数组。

在这里插入图片描述

vector与普通数组区别:不同之处在于数组是静态空间,而vector可以动态扩展。 动态扩展并不是在原空间之后续接新空间,而是找更大的内存空间,然后将原数据拷贝新空间,释放原空间。

  • vector是将元素置于一个动态数组中加以管理的容器
  • vecotr可以随机存取元素(支持索引值)直接存取,用[]操作符或at()方法)
  • vector尾部添加或移除元素非常快速,但在中部或头部插入元素或移除元素比较费时
  • vector的元素地址是连续的,动态扩容后可能地址会发生变化,即可能会在一块新的地址重新放新的连续的元素

vector的使用

头文件:

#include <iostream>
#include <vector>
using namespace std;

定义和初始化

像定义变量一样定义vector变量

vector<类型名> 变量名;

初始化的方式比较多,有如下几种:

1 vector<T> v1;                    //v1为空,执行默认初始化
2 vector<T> v2(v1);                //v2中包含v1所有元素的副本
3 vector<T> v2=v1;                //等价于v2(v1)
4 vector<T> v3(n,val);            //v3中包含n个重复元素,每个元素的值都是val
5 vector<T> v4(n);                //v4包含n个重复执行了值初始化的对象
6 vector<T> v5{a,b,c...};         //包含初始化元素个数,每个元素被对应的赋予相应的值
7 vector<T> v5={a,b,c...};        //等价v5{a,b,c...}

类型名可以是int、double、char、struct,也可以是STL容器:vector、set、queue。

vector<int> name;
vector<double> name;
vector<char> name;
vector<struct node> name;
vector<vector<int> > name;//注意:> >之间要加空格

注意:vector<vector<int> > name;>>之间要加空格。

vector数组就是一个一维数组,如果定义成vector数组的数组,那就是二维数组**。**

vector<int> array[SZIE]; //二维变长数组

在此,我送你一句话非常受用的话:低维是高维的地址。

二维数组中,它的一维形式就是地址。例如:

#include <iostream>
using namespace std;

int main(){
    int arr[3][2];//定义一个3行2列的地址
    cout<<arr[0]<<endl; //输出arr第1行的地址
    cout<<arr[1]<<endl; //输出arr第2行的地址
    cout<<arr[2]<<endl; //输出arr第3行的地址
    return 0;
}
/*运行结果:0x61fe00 //arr第1行的地址
0x61fe08 //arr第2行的地址
0x61fe10 //arr第3行的地址*/

所以,vector容器也可以这样理解。

构造函数

  • 无参构造函数:vector()
  • 指定大小和默认值的构造函数:vector(size_type n,const value_type& val=value_type())
  • 拷贝构造函数:vector(const vector& x)
  • 使用迭代器范围的构造函数:vector(InputIterator first,InputIterator last)

简单理解:创建vector的方法就像是买不同规格的箱子,有的箱子是空的(无参构造),有的箱子里已经装满了指定数量的物品(指定大小和默认值),有的箱子是完全照搬另一个箱子的东西(拷贝构造),还有的是根据一个范围内的物品来装箱(迭代器范围构造)。

功能描述:创建vector容器

函数原型

1. vector<T> v; //采用模版实现类实现,默认构造函数。T表示数据的类型,可以是int类型,也可以是string对象。
2. vector(v.begin(), v,end());  //将v[begin().end())区间(前闭后开)中的元素拷贝给本身。注意拷贝的元素是左闭右开区间
3. vector(n, elem);  //构造函数将n个elem拷贝给本身。
4. vector(const vector &vec);  //拷贝构造函数。

代码示例

#include <vector>
#include <iostream>
using namespace std;

int main()
{
    int iArray[]{ 1,2,3,4,5 };
    vector<int> vecIntA(iArray, iArray + 5);    //里面为1,2,3,4,5
    //将Array[0,5)中的元素拷贝给本身
    //vector<int> vecIntB(vecIntA.begin(), vecIntA.end());  //里面为1,2,3,4,5
    vector<int> vecIntB(vecIntA.begin() + 2, vecIntA.begin() + 5);   //里面为3,4,5
    vector<int> vecIntC(3, 9);  //里面为9,9,9,
    vector<int> vecIntD(vecIntC);   //拷贝构造函数调用,里面为9,9,9
    for (int i = 0; i < vecIntD.size(); i++)
    {
        cout << vecIntD[i] << endl;
    }
}
/*输出:9
9
9*/

总结: vector的多种构造方式没有可比性,灵活使用即可

赋值操作

功能描述: 给vector容器进行赋值

函数原型

5. vector& operator=(const vector &vec);  //重载等号操作符。
6. assign(begin,end);  //将[begin,end)区间中的数据拷贝赋值给本身。
7. assign(n,elem);  //将n个elem拷贝赋值给本身。

assign函数
功能:
通过assign函数改变vector内容(基于范围或者指定数量和初始值),这个容器会清除掉vector容器中以前的内容。
函数原型:
void assign(const_iterator first,const_iterator last);
void assign(size_type n,const T& x = T());

代码示例

#include <vector>
#include <iostream>
using namespace std;

int main( )
{
    // 定义三个存储int类型元素的vector容器对象,初始时它们都是空的
    vector<int> v1, v2, v3;  
    // 定义一个vector<int>类型的迭代器,用于遍历vector容器中的元素
    vector<int>::iterator iter;  

    // push_back 是 vector 容器提供的成员函数,用于在容器的末尾添加一个新元素。这里向 v1 容器依次添加了 10、20、30、40、50 这几个整数元素,使得 v1 容器中存储了这些值,v2同理
    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);  

    // 输出提示信息"v1 = ",准备输出v1容器中的元素
    cout << "v1 = " ;  
    // 通过迭代器iter遍历v1容器,从起始位置(v1.begin())开始,到结束位置(v1.end())结束,
    // 每次输出迭代器指向的元素(*iter),元素之间用空格隔开
    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;  

    // 使用赋值操作符将v1容器的所有元素复制给v2容器,会覆盖v2原来存储的元素
    v2 = v1;  
    cout << "v2 = ";  
    for (iter = v2.begin(); iter!= v2.end(); iter++)  
        cout << *iter << " ";
    cout << endl;  

    // 使用assign函数将v1容器中从起始位置(v1.begin())到结束位置(v1.end())的所有元素复制给v2容器
    v2.assign(v1.begin(), v1.end());  // 同样会覆盖v2原来存储的元素
    cout << "v2 = "; 
    for (iter = v2.begin(); iter!= v2.end(); iter++)  
        cout << *iter << " ";
    cout << endl;  

    // 使用assign函数给v3容器重新赋值,使其包含7个元素,并且每个元素的值都为3
    v3.assign(7, 3) ;  
    cout << "v3 = ";  
    for (iter = v3.begin(); iter!= v3.end(); iter++)  
        cout << *iter << " ";
    cout << endl;  
    return 0;  
}
/*运行结果:v1 = 10 20 30 40 50
v2 = 1 2
v2 = 10 20 30 40 50
v2 = 10 20 30 40 50
v3 = 3 3 3 3 3 3 3
*/

总结: vector赋值方式比较简单,使用operator=,或者assign都可以

容量和大小

功能描述: 对vector容器的容量和大小操作

函数原型:

8. empy(); //判断容器是否为空,空返回true,不为空返回false
9. capacity(); //容器的容量,capacity>=size
10. size();  //返回容器中元素的个数,capacity>=size
11. resize(int num);  //重新指定容器的长度为num,若容器变长,则以 默认值0 填充新位置。如果容器变短,则末尾超出容器长度的元素被删除。
                               //如果容器变短,则末尾超出容器长度的元素被删除。
12. resize(int num, elem); //重新指定容器的长度为num,若容器变成,则以 elem值 填充新位置。如果容器变短,则末尾超出容器长度的元素被删除。
  • vector 容器的容量(用 capacity 表示),指的是在不分配更多内存的情况下,容器可以保存的最多元素个数;而 vector 容器的大小(用 size 表示),指的是它实际所包含的元素个数。
  • vector 容器的大小不能超出它的容量,在大小等于容量的基础上,只要增加一个元素,就必须分配更多的内存。注意,这里的“更多”并不是 1 个。换句话说,当 vector 容器的大小和容量相等时,如果再向其添加(或者插入)一个元素,vector 往往会申请多个存储空间,而不仅仅只申请 1 个。
  • 一旦 vector 容器的内存被重新分配,则和 vector 容器中元素相关的所有引用、指针以及迭代器,都可能会失效,最稳妥的方法就是重新生成。
    代码示例
#include <iostream>#include <vector>#include <string>using namespace std;// 打印vector容器元素的函数void printVector(vector<int>& v){    for (vector<int>::iterator it = v.begin(); it!= v.end(); ++it){        cout << *it << "  ";    }    cout << endl;}​// vector容器构造及相关操作测试函数void test1(){    vector<int> v1;    // 向容器中插入元素    for (int i = 0; i < 10; ++i){        v1.push_back(i + 1);    }    // 输出容器v1的元素    cout << "v1:";    printVector(v1);​    // 判断容器是否为空并输出相应信息以及容量、大小信息    if (v1.empty()){        cout << "容器为空!" << endl;    }    else{        cout << "容器不为空!" << endl;        cout << "容器的容量为:" << v1.capacity() << endl;        cout << "容器的大小为:" << v1.size() << endl;    }    cout << string(50, '-') << endl;​    // 重新指定大小,比原来长,默认值0填充    v1.resize(12);    cout << "v1:";    printVector(v1);    cout << endl;    cout << string(50, '-') << endl;​    // 重新指定大小,比原来长,指定值1填充    v1.resize(15, 1);    cout << "v1:";    printVector(v1);    cout << endl;    cout << string(50, '-') << endl;​    // 重新指定大小,比原来短,把超出的部分删除    v1.resize(10);    cout << "v1:";    printVector(v1);    cout << endl;    cout << string(50, '-') << endl;}​int main(){    test1();    return 0;}/*运行结果:v1:1  2  3  4  5  6  7  8  9  10容器不为空!容器的容量为:13容器的大小为:10--------------------------------------------------v1:1  2  3  4  5  6  7  8  9  10  0  0​--------------------------------------------------v1:1  2  3  4  5  6  7  8  9  10  0  0  1  1  1​--------------------------------------------------v1:1  2  3  4  5  6  7  8  9  10​--------------------------------------------------*/

总结:

  • 判断是否为空 — empty
  • 返回元素个数 — size
  • 返回容器容量 — capacity
  • 重新指定大小 — resize

插入和删除

函数原型:

13. push_back(ele);  //尾部插入元素ele。
14. pop_back();  //删除最后一个元素。
15. insert(const_iterator pos, ele); //迭代器指向位置pos插入元素ele。
16. insert(const_iterator pos, int count ele); //迭代器指向位置pos插入count个元素。
17. erase(const_iterator pos); //删除迭代器指向的元素。
18. erase(cons_titerator start, const_iterator end);  //删除迭代器从start到end之间的元素。
19. clear();  //删除容器中所有元素。   

代码示例

#include <iostream> 
#include<vector> 
using namespace std;
void printVector(const vector<int>& vec)//形参使用const,避免被修改
{   //const_iterator只读迭代器
	for (vector<int>::const_iterator it = vec.begin(); it != vec.end(); ++it)
	{
		cout << *it<< ",";
	}
	cout << endl;
}
int main()
{
    vector<int> v;
	for (int i = 0; i < 5; i++)
	{
		v.push_back(i + 1);//尾部插入元素
	}
	printVector(v);//1 2 3 4 5
	
	v.insert(v.begin() + 1, 2, 100);//在第二个元素前插入2个100
	printVector(v);//1 100 100 2 3 4 5

	v.pop_back();//尾部删除一个元素
	printVector(v);//1 100 100 2 3 4
	cout << "-------------" << endl;
	v.erase(v.begin());//删除第一个元素
	printVector(v);//100 100 2 3 4

	vector<int>::const_iterator it=v.erase(v.begin() + 1, v.end() - 1);
	//删除从第二个元素到倒数第二个元素,返回下一个有效迭代器
	printVector(v);//100 4

	v.insert(it, 66);
	printVector(v);//100 66 4
	return 0;
}

数据存取

功能描述:对vector中的数据进行存取操作。

函数原型:

20. at(int idx);   ///返回索引为idx所指的数据。
21. operator[];  //返回索引idx所指的数据。
22. front();  //返回容器中第一个数据元素。
23. back();   //返回容器中最后一个数据元素。
24. swap(vec);  //将vec与本身的元素互换。
25. reserve(int len); //容器预留len个元素长度,预留位置不初始化,元素不可访问。

代码示例

#include <iostream>
#include<vector> 
using namespace std;
void printVector(vector<int> v)
{
    for (vector<int>::iterator it = v.begin(); it != v.end(); it++)
    {
        cout << *it << " ";
    }
    cout << endl;
}
int main()
{
    vector<int> v1;
    for (int i = 0; i < 10; i++)
    {
        v1.push_back(i);
    }
    //利用[]方式访问数组中元素
    for (int i = 0; i < v1.size(); i++)
    {
        cout << v1[i] << " ";
    }
    cout << endl;
    //利用at方式访问元素
    for (int i = 0; i < v1.size(); i++)
    {
        cout << v1.at(i) << " ";
    }
    cout << endl;
    //获取第一个元素
    cout << "第一个元素为:" << v1.front() << endl;
    //获取最后一个元素
    cout << "最后一个元素为:" << v1.back() << endl;
    return 0; 
}
/*运行结果:0 1 2 3 4 5 6 7 8 9
0 1 2 3 4 5 6 7 8 9
第一个元素为:0
最后一个元素为:9

互换容器

功能描述:实现两个容器内元素进行互换。

函数原型

24. swap(vec);  //将vec与本身的元素互换。

代码示例

#include <iostream>
#include<vector> 

using namespace std;


//vector容器互换

void printVector(vector<int>v)
{
    for (vector<int>::iterator it = v.begin(); it != v.end(); it++)
    {
        cout << *it << " ";
    }
    cout << endl;

}

//1、基本使用
void test06()
{
    cout << "交换前:" << endl;

    vector<int> v1;
    for (int i = 0; i < 10; i++)
    {
        v1.push_back(i);
    }
    
    printVector(v1);

    vector<int>v2;
    for (int i = 10; i > 0; i--)
    {
        v2.push_back(i);
    }
    printVector(v2);

    cout << "交换后:" << endl;
    v1.swap(v2);
    printVector(v1);
    printVector(v2);
}

//2、实际用途
//巧用swap可以收缩内存空间
void test07()
{
    vector<int>v;
    for (int i = 0; i < 100000; i++)
    {
        v.push_back(i);
    }
    cout << "v的容量为:" << v.capacity() << endl;
    cout << "v的大小为:" << v.size() << endl;

    v.resize(3);  //重新指定大小
    cout << "v的容量为:" << v.capacity() << endl;  //resize操作,容量并没有变,多余的容量浪费了
    cout << "v的大小为:" << v.size() << endl;

    //巧用swap收缩内存
    vector<int>(v).swap(v);  //vector<int>(v)创建了一个为匿名对象,会按v的大小初始化这个匿名对象容器的大小
                             //.swap(v)会对匿名对象容器与原容器做一个交换,则原容器的指针指向匿名对象的容器,匿名对象的容器的指针改为指向原容器
                             //	系统运行完创建匿名函数这一句语句后对匿名对象的指针(即地址、内存)进行回收

    cout << "v的容量为:" << v.capacity() << endl;
    cout << "v的大小为:" << v.size() << endl;
}

int main()
{
    test06();
    test07();

    return 0;
}

vector的迭代器

vector容器的迭代器是支持随机访问的迭代器

在这里插入图片描述

可以看到vector是左闭右开的容器,常用的迭代器是v. begin() 和v.end(),前者指向第一个元素,后者指向最后一个元素的下一个位置。vector容器还封装了很多对外接口,比如插值insert()、尾插法push_back()、尾删法pop_back()等等。

vector储存自定义数据类型

比如结构体

struct Student {
string name; // 名字
int age; // 年龄
};

int main() {
    vector<Student> class1; // 班级
    Student stu1, stu2;// 学生1,学生2
    stu1.name = "luobo";
    stu1.age = 12;
    stu2.name = "xiaoming";
    stu2.age = 25;
    class1.push_back(stu1);
    class1.push_back(stu2);
    return 0;
}

可以用下面的方式使用vector定义二维数组:

vector<vector<int>> vecvec = {{1, 2, 8}, {2, 4, 9}, {4, 7, 10}, {6, 8, 11}};

我们可以通过一个构造函数快速构建这样的一个动态数组,而用构造函数的写法和用循环是等价的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值