C++ [STL之vector的使用]

这篇具有很好参考价值的文章主要介绍了C++ [STL之vector的使用]。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

C++ [STL之vector的使用]

本文已收录至《C++语言》专栏!
作者:ARMCSKGT

C++ [STL之vector的使用]


前言

vector是可变大小的数组序列容器,一般也叫向量;底层原理是顺序表,但是vector是泛型容器,可以支持int,double甚至自定义类型的存储,在平时应用非常频繁且广阔,vector在很多场景下可以提高我们的开发效率,所以学习vector这一利器的使用是必须的!
C++ [STL之vector的使用]


正文

本文将介绍关于vector的常用接口,依据C++ vector官方文档!
首先在使用vector前,需要声明头文件 < vector > 且声明命名空间std!
vector是通过模板实例的泛型容器,需要指定类型进行实例化

默认成员函数


vector有三种常规构造,但是在C++11中又增加了一种好用的构造方法!
C++ [STL之vector的使用]


普通构造

vector支持以下构造:

  • 默认构造(生成一个空容器对象,没有任何数据)
  • 构造n个元素为val的对象
  • 迭代器区间构造
  • 列表初始化构造
#include <iostream>
#include <vector>
using namespace std;

int main()
{
	vector<int> v1; //默认构造

	vector<int> v2(5, 10); //构造5个元素为10的对象

	int arr[] = { 1,2,3,4,5 };
	vector<int> v3(arr, arr + (sizeof(arr) / sizeof(arr[0]))); //迭代器区间构造

	vector<int> v4 = { 6,7,8,9,10 }; //列表初始化构造

	return 0;
}

C++ [STL之vector的使用]


拷贝构造

我们在定义对象时,可以让新对象拷贝一个已存在的对象从而完成初始化!

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

int main()
{
	vector<int> v1(10, 1);

	//两种拷贝构造方式
	vector<int> v2(v1);
	vector<int> v3 = v1;

	return 0;
}

C++ [STL之vector的使用]


析构函数

析构函数在vector对象生命周期结束时自动调用,我们使用阶段不需要关心!


赋值重载

vector支持赋值拷贝一个对象(前提是该对象已经存在而并非构造),对与C++11支持通过列表初始化赋值!

C++ [STL之vector的使用]

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

int main()
{
	vector<int> v1 = {1,2,3};
	vector<int> v2;
	v2 = v1; //赋值空对象

	vector<int> v3 = { 4,5,6 };
	v3 = {10,11,12}; //通过列表赋值已存在数据的对象

	return 0;
}

C++ [STL之vector的使用]
可以发现当对象中存在数据时,对其赋值会情况原有数据,且也可以通过列表对vector对象进行初始化!


迭代器


  • vector支持两种迭代器正向和反向(C++11),这两种迭代器都有const版本!
  • 迭代器是将指针进行封装,构造成为迭代器对象,自己控制可操作行为!
  • vector的迭代器是随机迭代器,在支持++和- -的同时可以 ± 任意一个整数去往任意一个元素,所以可以使用sort排序!
    C++ [STL之vector的使用]

正向迭代器

正向迭代器的遍历,默认从头begin()到尾end()!
begin指向vector中第一个元素的位置,end指向最后一个元素的下一个位置!
C++ [STL之vector的使用]

在判断结束条件时不能使用 > 和 < 等,因为迭代器封装后不知道是否为连续的空间,判断是否等于end即可!

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

int main()
{
	vector<int> v = { 1,2,3,4,5 };
	vector<int>::iterator it = v.begin(); //定义vector<int>迭代器类型
	//auto it = v.begin(); //觉得麻烦也可以使用auto
	while (it != v.end())
	{
		cout << *it << " ";
		++it;
	}
	cout << endl;
	return 0;
}

C++ [STL之vector的使用]


反向迭代器

顾名思义,与正向迭代器相反!
rend指向vector中第一个元素的前一个位置,rbegin指向最后一个元素的位置!
C++ [STL之vector的使用]

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

int main()
{
	vector<int> v = { 1,2,3,4,5 };
	vector<int>::reverse_iterator rit = v.rbegin();
	while (rit != v.rend())
	{
		cout << *rit << " ";
		++rit;
	}
	cout << endl;
	return 0;
}

C++ [STL之vector的使用]
反向迭代器的++是从后向前走,与正向迭代器的行为相反!


const迭代器

在某些场景下例如:

//vector对象const引用传参,在函数中声明的迭代器是const迭代器
void Print(const vector<int>& v) {} 

//范围for使用const修饰元素时底层调用const迭代器
for (const auto& x : v) {}

平时我们很少会用到const迭代器,不过也可以主动定义!

vector<int>::const_iterator //const正向迭代器
vector<int>::const_reverse_iterator ///const反向迭代器

const迭代器无法修改迭代器指向的元素,但是可以更改迭代器的指向!


容量类


关于容量查询和修改的操作:
C++ [STL之vector的使用]


空间容量查询

vector支持以下容量查询操作:

  • 查询元素数量size
  • 查询当前容量capacity
  • 查询当前对象是否为空(不存在任何元素)empty
  • 查询对象可容纳最大元素数(预计,并非准确)max_size
#include <iostream>
#include <vector>
using namespace std;

int main()
{
	vector<int> v = { 1,2,3 };
	cout << "size:" << v.size() << endl;
	cout << "capacity:" << v.capacity() << endl;
	cout << "empty:" << (bool)v.empty() << endl;
	cout << "max_size:" << v.max_size() << endl;
	return 0;
}

C++ [STL之vector的使用]
关于max_size会因为实例类型不同,平台不同等因素发生改变!
C++ [STL之vector的使用]


空间容量操作

扩容操作

vector支持使用reserve函数手动扩容,在某些元素数已知的场景下可以提前开辟空间提高性能减少内存碎片!

首先,我们了解一下vector自己的扩容机制:

VS平台(PJ版本)
C++ [STL之vector的使用]
g++平台(SGI版本)
C++ [STL之vector的使用]
通过观察我们发现,VS下扩容是呈1.5倍,g++下是呈2倍扩容;这两种扩容策略各有优略,当数据量比较大时,VS频繁扩容导致性能下降;当数据量中等时,g++扩容冗余过多浪费空间!

针对这种情况,我们可以使用reserve提前扩容,避免这两种情况!

vector<int> v;
v.reverse(n); //提前将容量扩大到n

示例:

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

int main()
{
	vector<int> v;
	v.reserve(100);
	cout << "capacity:" << v.capacity() << endl;
	v.reserve(50); //reserve不支持缩容
	cout << "capacity:" << v.capacity() << endl;
	return 0;
}

C++ [STL之vector的使用]

元素数量操作

vector支持使用resize函数自定义元素数量大小,如果我们设置的数量大于当前容量就会触发扩容!

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

int main()
{
	vector<int> v = {1,2,3};
	cout << "size:" << v.size() << endl;
	cout << "capacity:" << v.capacity() << endl;
	
	v.resize(50);
	cout << "size:" << v.size() << endl;
	cout << "capacity:" << v.capacity() << endl;

	v.resize(10);
	cout << "size:" << v.size() << endl;
	cout << "capacity:" << v.capacity() << endl;

	return 0;
}

C++ [STL之vector的使用]
很显然,resize改变的是size的大小,无论怎样,也不会缩容!
如果resize(n)中,n大于当前的size,则新增长的空间会使用实例化类型的默认构造去初始化!
C++ [STL之vector的使用]
C++ [STL之vector的使用]
为了兼容自定义类型,内置类型也支持像定义对象一样初始化和构造,就是通过int()去构造,就像匿名对象一样,只不过int()相当于0!

int main()
{
	int a(1); //对象初始化方式
	int b = int(2); //匿名对象拷贝构造方式
	cout << a << endl;
	cout << b << endl;
	return 0;
}

C++ [STL之vector的使用]

当然resize也支持指定值进行初始化增长的空间

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

int main()
{
	vector<int> v = {1,2,3};
	v.resize(10,668); //指定初始化新元素空间为668
	return 0;
}

C++ [STL之vector的使用]
相当于reserve,resize既能扩容,还能完成初始化,两者各有应用场景!

缩容操作

C++11为容器提供缩容操作,缩容函数shrink_to_fit在平时用的非常少,因为对性能的消耗巨大!

vector<int> v(100,1);
v.shrink_to_fit(10); //将capacity缩小为10

其底层原理大概是根据空余的空间,重新开辟一片适当大小的空间并转移数据!
C++ [STL之vector的使用]


数据访问


vector是顺序表,其范围方式有很多种,除了通用的迭代器范围,还有以下方式可以访问数据:
C++ [STL之vector的使用]


下标访问

vector底层是顺序表,那必然支持下标随机访问!
下标访问的方式有两种,在原生通过[ ]访问的基础上,库中还有一个at()也可以通过下标访问,两者的区别在于:

  • 通过 [ ] 访问,如果下标越界则会报错
  • 通过 at() 访问如果下标越界会抛异常
#include <iostream>
#include <vector>
using namespace std;

int main()
{
	vector<int> v = {1,2,3};
	for (int i = 0; i < v.size(); ++i)
	{
		printf("v[%d]=%d,v.at(%d)=%d\n",i, v[i], i, v.at(i));
	}
	return 0;
}

C++ [STL之vector的使用]


头尾元素访问

vector支持取头尾元素的引用或const引用,平时用的比较少,了解即可!
C++ [STL之vector的使用]

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

int main()
{
	vector<int> v = { 1,2,3 };
	cout << v.front() << endl;
	cout << v.back() << endl;
	return 0;
}

C++ [STL之vector的使用]


获取原生指针

vector支持通过data函数获取存储元素的直接原生空间!
通过这个指针像访问数组一样,使用下标访问或*解引用访问和修改每一个空间的元素!
这个平时用的极少,且非常危险,不建议使用!

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

int main()
{
	vector<int> v = { 1,2,3 };
	int* p = v.data();
	p[1] = 4;
	for (const auto& x : v)
	{
		cout << x << endl;
	}
	return 0;
}

C++ [STL之vector的使用]


元素插入删除操作


vector有许多修改元素的操作函数,但我们只需要了解最常用的一部分即可!
C++ [STL之vector的使用]


尾插尾删

  • push_back(val)函数可以将val插入到当前vector容器尾部
  • pop_back()函数可以从当前容器尾部删除一个元素
#include <iostream>
#include <vector>
using namespace std;

void Print(const vector<int>& v)
{
	for (const auto& x : v)
	{
		cout << x << " ";
	}
	cout << endl;
}

int main()
{
	vector<int> v = { 4,5,6 };
	v.pop_back();
	Print(v);
	v.push_back(668);
	Print(v);
	return 0;
}

C++ [STL之vector的使用]


任意位置插入删除

C++ [STL之vector的使用]

任意位置插入

insert函数有三种形式,支持:

  • 在当前迭代器位置插入一个val元素(相当于在一个元素前插入一个元素)并返回新插入元素的迭代器
    这个返回值至关重要!当我们插入元素后,可能触发扩容,那么原迭代器就会失效(迭代器失效),此时insert会返回新的迭代器指向插入元素,以方便后续操作!
  • 在当前迭代器位置插入n个元素val元素,没有返回值
  • 在当前迭代器位置插入任意一个容器的迭代器区间,没有返回值
    对于这两个函数,在插入后必须手动更新迭代器,否则编译器会报错!
#include <iostream>
#include <vector>
using namespace std;

void Print(const vector<int>& v)
{
	for (const auto& x : v)
	{
		cout << x << " ";
	}
	cout << endl;
}

int main()
{
	vector<int> v = { 4,5,6 };
	v.insert(v.begin(), 1); //头插1
	Print(v);

	v.insert(v.begin(), 2); //头插1
	Print(v);

	v.insert(v.begin() + 2, 2, 668); //在2号元素前处插入2个668
	Print(v);

	int arr[] = { 9,6,3 };
	v.insert(v.begin() + 1, arr, arr + (sizeof(arr) / sizeof(arr[0]))); //在1号元素前插入一个数组
	Print(v);

	return 0;
}

C++ [STL之vector的使用]

任意位置删除

对于erase任意位置删除有两种形式:

  • 删除当前迭代器指向的元素,并返回该元素后的元素迭代器
  • 删除一个该容器迭代器区间,返回该区间后一个元素的迭代器
    删除操作必然会导致迭代器失效,所以每次删除操作都会更新迭代器!
#include <iostream>
#include <vector>
using namespace std;

void Print(const vector<int>& v)
{
	for (const auto& x : v)
	{
		cout << x << " ";
	}
	cout << endl;
}

int main()
{
	vector<int> v = {1,2,3,4,5,6,7,8,9,10};
	Print(v);
	v.erase(v.begin()); //头删
	Print(v);
	v.erase(v.begin() + 2, v.begin() + 7); //删除2-7号元素
	Print(v);
	return 0;
}

C++ [STL之vector的使用]
删除对于性能的消耗巨大,因为涉及挪动数据,平时使用也不多!


其他操作函数


交换函数

vector有自带的交换函数,其底层是交换双方所管理的空间!

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

void Print(const vector<int>& v)
{
	for (const auto& x : v)
	{
		cout << x << " ";
	}
	cout << endl;
}

int main()
{
	vector<int> v1 = { 1,2,3,4,5 };
	vector<int> v2 = { 6,7,8,9,10 };
	v1.swap(v2);
	Print(v1);
	Print(v2);
	return 0;
}

C++ [STL之vector的使用]
当然,vector也支持库中统一的swap函数,但是需要声明算法头文件algorithm才能使用!

#include <iostream>
#include <vector>
#include <algorithm> //算法头文件
using namespace std;
int main()
{
	vector<int> v1 = { 1,2,3,4,5 };
	vector<int> v2 = { 6,7,8,9,10 };
	swap(v1,v2);
	return 0;
}

清空函数

clear函数可以将当前vector对象的元素全部清空,但是不会缩容也不会销毁对象!

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

void Print(const vector<int>& v)
{
	for (const auto& x : v)
	{
		cout << x << " ";
	}
	cout << endl;
}

int main()
{
	vector<int> v = { 1,2,3,4,5 };
	cout << "size:" << v.size() << endl;
	cout << "capacity:" << v.capacity() << endl;
	v.clear();
	cout << "size:" << v.size() << endl;
	cout << "capacity:" << v.capacity() << endl;
	return 0;
}

C++ [STL之vector的使用]


最后

vector的使用介绍到这里就结束了,vector是一款强大的泛型顺序表,他弥补了数组无法动态扩容的缺点,以及泛型思想使得vector可以实例化成任何类型的顺序表,但只其实现只有一份代码;后面我会为大家揭开vector底层的秘密,为大家介绍vector的底层实现!

本次 <C++ vector使用> 就先介绍到这里啦,希望能够尽可能帮助到大家。

如果文章中有瑕疵,还请各位大佬细心点评和留言,我将立即修补错误,谢谢!

C++ [STL之vector的使用]

🌟其他文章阅读推荐🌟
C++ <STL之string的使用> -CSDN博客
C++ <STL之string模拟实现> -CSDN博客
C++ <STL简介> -CSDN博客
C++ <模板> -CSDN博客
C++ <内存管理> -CSDN博客
🌹欢迎读者多多浏览多多支持!🌹

​​

​​


文章来源地址https://www.toymoban.com/news/detail-459913.html

到了这里,关于C++ [STL之vector的使用]的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【C++初阶】C++STL详解(三)—— vector的介绍及使用

    ​ ​📝个人主页:@Sherry的成长之路 🏠学习社区:Sherry的成长之路(个人社区) 📖专栏链接:C++学习 🎯 长路漫漫浩浩,万事皆有期待 上一篇博客:【C++】string类常见题目详解(二) —— 把字符串转换成整数、反转字符串、反转字符串 II、反转字符串中的单词 III、字符

    2024年02月11日
    浏览(47)
  • [C++] STL_vector使用与常用接口的模拟实现

    vector文档介绍 vector是表示可变大小数组的序列容器。 就像数组一样,vector也采用的连续存储空间来存储元素。也就是意味着可以采用下标对vector的元素进行访问,和数组一样高效。但是又不像数组,它的大小是可以动态改变的,而且它的大小会被容器自动处理。 本质讲,

    2024年02月11日
    浏览(33)
  • 【C++】STL---vector

    vector 是表示可变大小数组的序列容器。 就像数组一样, vector 也采用的连续存储空间来存储元素。也就是意味着可以采用下标对 vector 的元素进行访问,和数组一样高效。但是又不像数组,它的大小是可以动态改变的,而且它的大小会被容器自 动处理。 本质讲, vector 使用动

    2024年02月11日
    浏览(35)
  • C++ STL vector

    目录 一.认识vector 二.vector的使用 1.vector的构造函数 2.vector的迭代器 2.1 begin(),end() 2.2 rbegin(),rend() 2.3 迭代器初始化对象  3. vector 增删查改 3.1push_back(),pop_back() 3.2  insert(),erase() 3.3 operator[]  4.vector 空间控制 4.1 size(),capacity(),empty() 4.2 r

    2024年02月13日
    浏览(35)
  • STL 关于vector的细节,vector模拟实现【C++】

    _start指向容器的头,_finish指向容器当中 有效数据 的下一个位置,_endofstorage指向整个容器的尾 先开辟一块与该容器大小相同的空间,然后将该容器当中的数据一个个拷贝过来即可,最后更新_finish和_endofstorage的值即可。 深拷贝版本一: 注意: 不能使用memcpy函数 , 如果vec

    2024年02月15日
    浏览(43)
  • 【C++ STL】vector模拟实现

    2023年05月17日
    浏览(50)
  • C++ STL vector 模拟实现

    ✅1主页:我的代码爱吃辣 📃2知识讲解:C++之STL 🔥3创作者:我的代码爱吃辣 ☂️4开发环境:Visual Studio 2022 💬5前言:上次我们已经数字会用了vector,这次我们对其底层更深一步挖掘,其中重点是,Vector中一些深浅拷贝问题。 目录 一.Vector模拟实现的整体框架 二. Vector的构

    2024年02月13日
    浏览(32)
  • 【C++】STL---vector基本用法介绍

    个人主页:平行线也会相交💪 欢迎 点赞👍 收藏✨ 留言✉ 加关注💓本文由 平行线也会相交 原创 收录于专栏【C++之路】💌 本专栏旨在记录C++的学习路线,望对大家有所帮助🙇‍ 希望我们一起努力、成长,共同进步。🍓 vector 是 C++STL 中的一种 动态数组容器 ,用于存储和

    2024年02月16日
    浏览(46)
  • C++ [STL之vector模拟实现]

    本文已收录至《C++语言》专栏! 作者:ARMCSKGT vector是STL容器容器之一,其底层实现类似于数据结构顺序表,相当于string来说得益于泛型模板的加持使得vector可以变为任何类型,且是可以动态扩容,堪称大号数组!在vector的实现中,有许多值得我们学习的细节,接下来将为大家

    2024年02月11日
    浏览(41)
  • 【C++】STL 模拟实现之 vector

    vector 是我们学习的第一个真正的 STL 容器,它接口的使用方式和 string 有一点点的不同,但大部分都是一样的,所以这里我们就只演示其中一些接口的使用,大家如果有疑惑的地方直接在 cplusplus 是上面查看对应的文档即可。 vector 提供了四种构造方式 – 无参构造、n 个 val 构

    2023年04月27日
    浏览(44)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包