C++初阶学习第八弹——探索STL奥秘(三)——深入刨析vector的使用

简介: C++初阶学习第八弹——探索STL奥秘(三)——深入刨析vector的使用

前言:

在前面我们已经学习了string的使用和模拟实现,它们在使用上有异曲同工之妙,所以在学习了string之后我们再学习vector就会容易很多,下面跟着我的脚步我们来学习一下vector的具体用法


一、vector的基本概念

vector和string一样,都是属于C++模板库中的部分:

Vector,中文名称为“向量”,是C++ STL(Standard Template Library,标准模板库)中的一种数据结构,它是一个动态数组,可以动态地增加或减少其大小。vector在内存中是连续存储的,这意味着它的所有元素都存储在内存中相邻的位置。

基本概念:

vector是一个模板类,定义在头文件(include<vector>)中。可以使用vector来存储任意类型的对象,包括自定义类型。

vector有以下几个重要的特点:

  1. 可动态增长:vector可以动态地增加其大小,无需重新分配内存。
  2. 可动态缩小:vector可以动态地缩小其大小,释放不需要的内存。
  3. 支持随机访问:vector支持随机访问,这意味着可以通过下标快速访问vector的元素。
  4. 支持插入和删除:vector支持在头或尾插入和删除元素,但在中间插入和删除元素的效率较低。


二、vector的使用

接下来我们就来学习一下vector的基本使用方法,由于之前我们已经有了string的学习基础,所以在下面我们会讲的较为快速一些,主要就讲一下vector的几个比较常用的用法,我们的重心还是放在后面vector的模拟实现上

2.1 vector在库中的存在方式及常见接口

我们先来看一下vector在库中的存在形式

这其中涉及到类模板和容器的问题,这些目前我们还没有学到,等我们后面学到了再讲

vector由于是一个容器,它支持不同类型的数据进行操作,所以这个写法上与string还是有不少区别,如vector在定义一个变量时的方式为:

vector<int> v1;
vector<double> v2;
vector<string> v3;

我们先来看一下vector的一些比较重要的接口函数:

下面我们就先来讲一下几个比较重要的接口函数

2.2 vector的构造

vector的构造方式上与string并没有太大区别,主要也是无参的默认构造,初始化构造,拷贝构造等,没有太大的难度,下面的讲解会直接给出代码实例

代码实例如下:

#include<iostream>
#include<vector>
using namespace std;
 
// 1、测试vector的几种构造方法
void test1_vector()
{
  vector<int>();    //这种的会发生隐式类型转换,但只在本行起作用
  vector<int> v1;   //无参构造
  vector<int> v2(10, 100);   //构造一个vector有10个100
  vector<int> v3(v2);    //拷贝构造
  vector<int> v4(v2.begin(), v2.end());   //迭代器构造
  //下面还有一种迭代器构造的方式,这里涉及了迭代器的初始化,我们在下面会讲
  int arr[] = { 16,2,77,29 };
  vector<int> v5(arr, arr + sizeof(arr) / sizeof(int));
 
  cout << "The contents of v5 are:";
  for (vector<int>::iterator it = v5.begin(); it != v5.end(); ++it)
    cout << ' ' << *it;
  cout << '\n';
}
int main()
{
  test1_vector();
  return 0;
}

运行结果:

2.3 vector迭代器的使用

这里的使用与string类似,我们往下看:

代码实例:

void test2_vector()
{
  vector<int> v1;
  v1.push_back(1);
  v1.push_back(2);
  v1.push_back(3);
  v1.push_back(4);
  //正向迭代器1
  vector<int>::iterator it = v1.begin();
  while (it != v1.end())
  {
    cout << *it << " ";
    ++it;
  }
  cout << endl;
  //正向迭代器2
  for (auto e : v1)     //for循环的本质其实就是迭代器,而且它还会自己++
  {
    cout << e << " ";
  }
  cout << endl;
  //反向迭代器
  vector<int>::reverse_iterator rt = v1.rbegin();
  while (rt != v1.rend())
  {
    cout << *rt << " ";
    rt++;
  }
  cout << endl;
}

运行结果:

正反向迭代器在vector中的应用是很好理解的

2.4 vector的空间增长问题

注意事项:

1、vector在不同环境下的默认扩容速度是不同的,一般是1.5倍或者2倍

2、reverse只负责开辟空间,一般在知道需要多少空间的时候可以调用该函数,省去了扩容的麻烦

3、resize不仅可以扩容,还可以进行初始化来改变size


上面的这些重点就是resize和reverse两项,我们先把这两个单拎出来看一下:

resize有两个参数,一个是开辟空间大小,一个是初始化大小

reverse只有一个参数,就是开辟空间大小

代码示例:

void test3_vector()
{
  vector<int> v1;
  v1.reserve(100);         //开辟一个100大小的空间
  cout << v1.capacity() << endl;
 
  vector<int> v2;
  v2.resize(10);          //开辟一个10个大小的空间,同时改变size,并通过半缺省来初始化
  for (auto e : v2)
  {
    cout << e << " ";
  }
  cout << endl;
 
  vector<int> v3;
  v3.resize(10, 3);  //将数据初始化为3
  for (auto e : v3)
  {
    cout << e << " ";
  }
  cout << endl;
}

运行结果:

2.5 vector的增删查改

这些全部通过接口函数来实现,难度不大

代码实例:

void test4_vector()
{
  vector<int> v1;
  //增——push_back(尾插)
  v1.push_back(1);
  v1.push_back(2);
  v1.push_back(3);
  v1.push_back(4);
  cout << "增:";
  for (auto e : v1)
  {
    cout << e << " ";
  }
  cout << endl;
 
  //删——pop_back(尾删)
  v1.pop_back();
  cout << "删:";
  for (auto e : v1)
  {
    cout << e << " ";
  }
  cout << endl;
 
  //查——find(这个是算法库中的接口,不是vector的接口,返回类型是查找位置的迭代器)
  auto pos1 = find(v1.begin(), v1.end(), 2);
  cout << "查:";
  cout << *pos1 << endl;    //如果没找到就不进行任何操作
 
  //在任意位置插入——insert
  //要先用find找到要插入的位置,然后再插入数据
  auto pos2 = find(v1.begin(), v1.end(), 2);
  if (pos2 != v1.end())
  {
    v1.insert(pos2, 20);
  }
  cout << "插入任意位置:";
  for (auto e : v1)
  {
    cout << e << " ";
  }
  cout << endl;
 
  //在任意位置删除——erase
  //同样要先用find找到要删除的位置,然后再删除数据
  auto pos3 = find(v1.begin(), v1.end(), 2);
  v1.erase(pos3);
  cout << "删除任意位置:";
  for (auto e : v1)
  {
    cout << e << " ";
  }
  cout << endl;
 
  //改——operator[]
  v1[0] = 100;
  cout << "改:";
  for (auto e : v1)
  {
    cout << e << " ";
  }
  cout << endl;
}

运行结果:

三、总结

以上就是vector的用法讲解,相比于string,vector的使用范围其实更广,vector的难点在于其模拟实现上,这个我们后面就讲

感谢各位大佬观看,创作不易,还请各位大佬点赞支持!!

相关文章
|
1天前
|
存储 缓存 C++
C++ 容器全面剖析:掌握 STL 的奥秘,从入门到高效编程
C++ 标准模板库(STL)提供了一组功能强大的容器类,用于存储和操作数据集合。不同的容器具有独特的特性和应用场景,因此选择合适的容器对于程序的性能和代码的可读性至关重要。对于刚接触 C++ 的开发者来说,了解这些容器的基础知识以及它们的特点是迈向高效编程的重要一步。本文将详细介绍 C++ 常用的容器,包括序列容器(`std::vector`、`std::array`、`std::list`、`std::deque`)、关联容器(`std::set`、`std::map`)和无序容器(`std::unordered_set`、`std::unordered_map`),全面解析它们的特点、用法
C++ 容器全面剖析:掌握 STL 的奥秘,从入门到高效编程
|
1天前
|
存储 算法 C++
深入浅出 C++ STL:解锁高效编程的秘密武器
C++ 标准模板库(STL)是现代 C++ 的核心部分之一,为开发者提供了丰富的预定义数据结构和算法,极大地提升了编程效率和代码的可读性。理解和掌握 STL 对于 C++ 开发者来说至关重要。以下是对 STL 的详细介绍,涵盖其基础知识、发展历史、核心组件、重要性和学习方法。
|
3天前
|
算法 编译器 C++
模拟实现c++中的vector模版
模拟实现c++中的vector模版
|
25天前
|
C++ 容器
【c++丨STL】stack和queue的使用及模拟实现
本文介绍了STL中的两个重要容器适配器:栈(stack)和队列(queue)。容器适配器是在已有容器基础上添加新特性或功能的结构,如栈基于顺序表或链表限制操作实现。文章详细讲解了stack和queue的主要成员函数(empty、size、top/front/back、push/pop、swap),并提供了使用示例和模拟实现代码。通过这些内容,读者可以更好地理解这两种数据结构的工作原理及其实现方法。最后,作者鼓励读者点赞支持。 总结:本文深入浅出地讲解了STL中stack和queue的使用方法及其模拟实现,帮助读者掌握这两种容器适配器的特性和应用场景。
56 21
|
1月前
|
C++ 开发者
C++学习之继承
通过继承,C++可以实现代码重用、扩展类的功能并支持多态性。理解继承的类型、重写与重载、多重继承及其相关问题,对于掌握C++面向对象编程至关重要。希望本文能为您的C++学习和开发提供实用的指导。
58 16
|
2月前
|
编译器 C语言 C++
【c++丨STL】list模拟实现(附源码)
本文介绍了如何模拟实现C++中的`list`容器。`list`底层采用双向带头循环链表结构,相较于`vector`和`string`更为复杂。文章首先回顾了`list`的基本结构和常用接口,然后详细讲解了节点、迭代器及容器的实现过程。 最终,通过这些步骤,我们成功模拟实现了`list`容器的功能。文章最后提供了完整的代码实现,并简要总结了实现过程中的关键点。 如果你对双向链表或`list`的底层实现感兴趣,建议先掌握相关基础知识后再阅读本文,以便更好地理解内容。
46 1
|
2月前
|
算法 网络安全 区块链
2023/11/10学习记录-C/C++对称分组加密DES
本文介绍了对称分组加密的常见算法(如DES、3DES、AES和国密SM4)及其应用场景,包括文件和视频加密、比特币私钥加密、消息和配置项加密及SSL通信加密。文章还详细展示了如何使用异或实现一个简易的对称加密算法,并通过示例代码演示了DES算法在ECB和CBC模式下的加密和解密过程,以及如何封装DES实现CBC和ECB的PKCS7Padding分块填充。
68 4
2023/11/10学习记录-C/C++对称分组加密DES
|
2月前
|
存储 对象存储 C++
C++ 中 std::array<int, array_size> 与 std::vector<int> 的深入对比
本文深入对比了 C++ 标准库中的 `std::array` 和 `std::vector`,从内存管理、性能、功能特性、使用场景等方面详细分析了两者的差异。`std::array` 适合固定大小的数据和高性能需求,而 `std::vector` 则提供了动态调整大小的灵活性,适用于数据量不确定或需要频繁操作的场景。选择合适的容器可以提高代码的效率和可靠性。
101 0
|
2月前
|
算法 C语言 C++
【c++丨STL】list的使用
本文介绍了STL容器`list`的使用方法及其主要功能。`list`是一种双向链表结构,适用于频繁的插入和删除操作。文章详细讲解了`list`的构造函数、析构函数、赋值重载、迭代器、容量接口、元素访问接口、增删查改操作以及一些特有的操作接口如`splice`、`remove_if`、`unique`、`merge`、`sort`和`reverse`。通过示例代码,读者可以更好地理解如何使用这些接口。最后,作者总结了`list`的特点和适用场景,并预告了后续关于`list`模拟实现的文章。
69 7
|
2月前
|
存储 编译器 C语言
【c++丨STL】vector模拟实现
本文深入探讨了 `vector` 的底层实现原理,并尝试模拟实现其结构及常用接口。首先介绍了 `vector` 的底层是动态顺序表,使用三个迭代器(指针)来维护数组,分别为 `start`、`finish` 和 `end_of_storage`。接着详细讲解了如何实现 `vector` 的各种构造函数、析构函数、容量接口、迭代器接口、插入和删除操作等。最后提供了完整的模拟实现代码,帮助读者更好地理解和掌握 `vector` 的实现细节。
67 0