团学工作
  首页 >   员工工作 >   团学工作 > 正文
C++STL初探之vector
发布时间:2019年06月08日 11:35 作者: 审核: 校对:杨登陆 来源: 浏览次数:

STL(StandardTemplateLibrary),即标准模板库,是一个具有工业强度的,高效的C++程序库。它拥有六大组件,分别为容器(Container),迭代器(Iterator),算法(Algorithm),仿函数(Function object),迭代适配器(Adaptor),空间配制器(allocator)。本篇文章带你走进STL中使用最为广泛的一个容器——vector,通过这篇文章,你将了解到vector基本的内部构造以及使用方法。

顾名思义,vector意为向量,可以存储一维数组,二维数组和多维数组,但是它又比数组更优越,数组不能动态扩展,因此在程序运行的时候不是浪费内存,就是造成越界。而vector正好弥补了这个缺陷,vector可以动态扩展,同时也像数组一样通过下标访问。vector上常见操作复杂度如下:

· 随机访问——常数O(1)

· 在末尾插入或移除元素——均摊常数O(1)

· 插入或移除元素——与到vector结尾的距离成线性O(n)

下面我们先介绍一下vector的使用方法,使用vector首先需要添加其头文件,其头文件名也是vector,同时需要传入一个模板参数,参数必须是完整类型并满足可擦除(Erasable)的要求,即接受有可访问析构函数的类类型和所有标量类型,但拒绝数组类型、函数类型、引用类型和void。

初始化

std::vector<int>v1; //vector元素为int型,无初始值

std::vector<string>v2; //vector元素为string型,无初始值

std::vector<int>v3={1,2,3,4}; //vector元素为int类型,且包含四个整数1,2,3,4

std::vector<int>v4(3,100); //vector元素为int类型,包含三个整数100,100,100

添加元素

在C++11之前,添加元素一般用push_back和insert函数

std::vector<int>numbers;

// push_back

numbers.push_back(15);

numbers.push_back(16);

std::cout<<"插入到vector末尾,vector元素排列为:";

for(inti:numbers)

std::cout<<i<<"";

std::cout<<std::endl;

//输出:插入到vector末尾,vector元素排列为:15 16

// insert

numbers.insert(numbers.begin(),14);

std::cout<<"插入到vector首位,vector元素排列为:";

for(inti:numbers)

std::cout<<i<<"";

std::cout<<std::endl;

//输出:插入到vector首位,vector元素排列为:14 15 16

从C++11起,vector允许我们在容器末尾就地构造元素,,这样可以避免用push_back时的额外复制或移动操作,如下所示(此示例代码来自C++官方文档)

#include <vector>

#include <string>

#include <iostream>

structPresident

{

std::stringname;

std::stringcountry;

intyear;

President(std::stringp_name,std::stringp_country,intp_year)

:name(std::move(p_name)),country(std::move(p_country)),year(p_year)

{

std::cout<<"I am being constructed.\n";

}

President(President&&other)

:name(std::move(other.name)),country(std::move(other.country)),year(other.year)

{

std::cout<<"I am being moved.\n";

}

President&operator=(constPresident&other)=default;

};

intmain()

{

std::vector<President>elections;

std::cout<<"emplace_back:\n";

elections.emplace_back("Nelson Mandela","South Africa",1994);

std::vector<President>reElections;

std::cout<<"\npush_back:\n";

reElections.push_back(President("Franklin Delano Roosevelt","the USA",1936));

std::cout<<"\nContents:\n";

for(Presidentconst&president:elections) {

std::cout<<president.name<<" was elected president of "

<<president.country<<"in "<<president.year<<".\n";

}

for(Presidentconst&president:reElections) {

std::cout<<president.name<<" was re-elected president of "

<<president.country<<"in "<<president.year<<".\n";

}

}

//输出:

emplace_back:

Iambeingconstructed.

push_back:

Iambeingconstructed.

Iambeingmoved.

Contents:

NelsonMandelawaselectedpresidentofSouthAfricain1994.

FranklinDelanoRooseveltwasre-electedpresidentoftheUSAin1936.

删除元素

删除元素包括删除末尾元素和删除指定元素

//初始化一个含有五个int型(1,2,3,4,5)的vector容器

std::vector<int>numbers={1,2,3,4,5};

// pop_back

numbers.pop_back();

numbers.pop_back();

std::cout<<"删除vector末尾一个元素,vector元素排列为:";

for(inti:numbers)

std::cout<<i<<"";

std::cout<<std::endl;

//输出:删除vector末尾一个元素,vector元素排列为:1 2 3

// erase

numbers.erase(numbers.begin()); //删除开始第一个元素

std::cout<<"删除vector开始一个元素,vector元素排列为:";

for(inti:numbers)

std::cout<<i<<"";

std::cout<<std::endl;

//输出:删除vector开始一个元素,vector元素排列为:2 3

其他

std::vector<int>numbers;

//查看是否为空

std::cout<<numbers.empty()<<std::endl;

//清除内容

numbers.clear();

//查看容纳的元素数

std::cout<<numbers.size()<<std::endl;

//查看可容纳的最大元素数

std::cout<<numbers.max_size()<<std::endl;

//查看当前存储空间能够容纳的元素数

std::cout<<numbers.capacity()<<std::endl;

介绍完vector基本的使用方法之后,我们来分析一下vector内部是怎样工作的,下图是vector<T>的内存映像

_first指针指向vector的首元素,_last指向末尾元素,_end指向vector构造出的预留空间的末尾,vector里面有2个成员函数size()和capacity(),capacity()返回vector当前实际空间大小,这部分空间一部分存储元素,另一部分作为预留空间。而size()返回的是当前对象所包含的元素个数。显然,capacity是大于等于size的,当size和capacity相等时,如果继续添加元素,vector就会扩容。一般情况下扩展之后容量等于扩展之前容量的两倍(在VS上运行则是1.5倍),下面我们以一个程序来看一下扩展操作

std::vector<int>vec={1,2,3,4};

std::cout<<"扩展前:"<<std::endl;

std::cout<<"元素个数:"<<vec.size()<<std::endl;

std::cout<<"当前容量:"<<vec.capacity()<<std::endl;

//扩展前:

//元素个数:4

//当前容量:4

vec.push_back(5);

std::cout<<"\n扩展后:"<<std::endl;

std::cout<<"元素个数:"<<vec.size()<<std::endl;

std::cout<<"当前容量:"<<vec.capacity()<<std::endl;

//扩展后:

//元素个数:5

//当前容量:8

作为动态数组,vector有一个指针指向一片连续的内存空间。但是,这个内存空间肯定不是无限大的,当现有容量装不下所有数据时,系统会自动申请一片更大的空间,把原来的数据拷贝过去,释放原来的内存空间。最大可以容纳的元素个数可以通过函数max_size()得到。

更多关于vector请访问C++官方文档之vector

关闭