C++菜鸟学习笔记系列(8)——标准库类型vector

简介: C++菜鸟学习笔记系列(8)——标准库类型vector

C++菜鸟学习笔记系列(8)

本期主题:标准库类型vector

在上一篇C++菜鸟学习笔记系列(7)博客中我们对标准库类型 string 进行了相关介绍。vector也是一种非常重要的标准库类型,在这一篇博客中作者将从定义和初始化、添加元素、使用索引等方面来介绍一些关于C++语言标准库类型 vector 的使用方法。


标准库类型 vector 表示对象的集合,其中所有对象的类型都相同。与string类型相似的,集合中的每个对象都有一个与之对应的索引,索引可以用于访问对象。因为“ vector”中存放着其他对象,所以它也常常被称为容器(后面我们再做详细介绍)

我们在使用 vector 类型时也要包含相应的头文件,这里我们使用:

#include <vector>

1. 定义和初始化vector对象

vector能够容纳绝大多数类型的对象作为其元素,同时也可以容纳我们自定义的类型对象。由此我们可以得到我们在C++菜鸟学习笔记系列(4)中所介绍的引用并不是对象,所以不存在包含引用的 vector 。除此之外, vector 本身也是一个对象,所以其还可以作为自己的元素。

下面我们来看一下如何定义和初始化一个vector对象:

vector <T> v1;

这是我们定义一个vector对象最常用的方式,v1是一个空的vector,它的潜在元素时T类型,执行默认初始化,初始化的值会由T的类型决定,例如T为int类型则初始化的值为0,如果T为string类型则默认为“”。

我们看起来空 vector 对象没有什么用,但是很快我们会知道C++程序在运行时可以很高效的往 vector 对象中添加元素。事实上我们并没有必要在创建vector 对象时初始化好元素,相反的创建一个空 vector 对象,然后再向其添加元素是一种非常常见的使用方式。


列表初始化vector对象

C++11新标准为我们提供了一种为vector对象的元素赋初值的方法,即猎鸟初始化。此时用{}括起来的0个或多个初始元素值就被赋给vector对象。

vector <int> v2 {1, 2, 3};
vector <string> v3 { "123", "456", "789" };

上面的代码表示我们初始化了两个vector对象其中 v2 表示含有1 2 3三个int元素, v3 表示含有"123" “456” "789"三个string元素。

注意:上面的花括号{}不能使用圆括号()代替。


还有一种情况是我们在初始化过程中所要初始化的值是多个重复的,这时候如果我们还是像上述的方法一样去重复多个赋值的话就会显得特别冗余。由此我们就要引申出给定容量值构造初始化的方法。


给定容量值构造初始化

vector <int> v4 (10,1);
vector <string> v5 (10,"ha");

简单描述一下上述代码,第一行10代表所定义vector对象v4中容纳的元素 1 的个数。第二行也是类似的。

通常情况下我们还可以略去初始值而只提供vector对象容纳元素的数量。此时库会创建一个值初始化的元素初值,并把它赋给容器中的所有元素。当然,这个初值由vector对象中的元素类型所决定。

vector <int> v4 (10);
vector <string> v5 (10);

我们把初始化的代码改成如上所示,则代表v4对象中有10个0,v5对象中有10个空字符串“”。但是对于上述定义方法如果对象中的元素类型不支持默认初始化,我们就必须提供初始值,否则只提供元素的数量不提供初始值无法完成初始化的工作。


某些情况下,初始化的真实含义还取决于传递值时使用的是花括号还是圆括号。例如:

vector <int> v6 (10 , 1);// v6有10个元素,每个值都是1
vector <int> v7 {10 , 1};// v7有2个元素,一个值为10,另一个值为1

如上所示,如果是使用了圆括号我们认为是构造初始化花括号我们则认为是列表初始化

注意:关于这一方面还有很多注意点,很冗长,这里就不过多介绍了。

2.向vector对象中添加元素

我们在第一节中已经提到创建一个空的vector对象然后再向其中添加元素值是一个非常常见的使用方式。这是很有道理的,例如我们想要创建一个vector对象包含从1-99的整型数,那我们总不能在定义初始化的时候就把1-99这99个整型数全部输入进去吧。

C++语言为我们提供了vector对象中的成员函数push_back,push_back负责把一个值当做是vector对象的尾元素“压到”vector对象的“尾端”。

下面我们来看一个小例子:

/*
Author: wxc_1998
Date: 2018/10/1
*/
#include <iostream>
#include <vector>
#include <string>
using namespace std;
void main()
{
  string word;
  vector <string> v1;
  while (cin >> word)
  {
    v1.push_back( word );
  }
  cout << "over!!!" << endl;
  cout << "press any key to continue!";
    cin.clear();
    cin.sync();
    cin.get();
}

通过上述代码我们可以看到,我们每次循环通过变量word向vector对象中添加一个 string 类型的元素。

3. vector对象中的索引

和string类型相似的,我们也可以通过下标运算符获取到指定的 vector 元素。vector 对象的下标也是从0开始记起,且其值必须小于vector.size()。

下面我们看一个小例子:

/*
Author: wxc_1998
Date: 2018/10/1
*/
#include <iostream>
#include <vector>
using namespace std;
void main()
{
  vector <int> v;
  cout << "please input the data(int):" << endl;
  int i;
  while (cin >> i)
  {
    v.push_back(i);
  }
  for (int j = 0; j < v.size(); j++ )
  {
    v[j] *= v[j];
  }
  cout << "the square of each element : " << endl;
  for (int k= 0; k < v.size(); k++ )
  {
    cout << v[k] << " ";
  }
  cout << endl << "press any key to continue!";
    cin.clear();
    cin.sync();
    cin.get();
}

上述代码我们实现了输入一组整型数,输出每个数的平方值的功能,由代码我们可以看到对于vector对象的索引使用。

输出结果为:

96447814-120fc980-1245-11eb-938d-6ea408716c72.png

索引的使用可以让我们方便的去访问vector对象中的每一个元素,我们可以通过索引对vector对象访问、赋值等操作,但是我们最好不要试图通过索引为vector对象添加元素。例如下面所示的代码:

vector <int> v;
for (int i = 0 ;i < 10 ; i++ )
{
  v[i] = i;
}

我们看上去没有什么语法错误,但是我们仔细分析一下可以知道:vector对象v在创建时是一个空的对象,里面没有任何元素,然后我们在for循环体中却又使用下标去访问v[i],这不是一个明显的错误吗?这种错误是不会被编译器发现的,而是会产生一个不可预知的值。


这种通过下标访问不存在的行为非常常见,而且会产生很严重的后果。所谓的缓冲区溢出就是指这种错误,这也是导致PC机及其他设备上应用程序出现安全问题的一个重要原因。

(引自:C++primer)


所以我们在使用索引时一定要注意下标运算符只能用于访问已经存在的元素,而不能用于添加元素。


好了,这次就写到这里了,我们下次再见。


祝大家国庆节快乐!愿祖国繁荣昌盛!


注:虽然这篇博客的内容十分简单,但是大家若有转载还请标明出处!


还有大家若对博客中的内容有任何问题可以随时联系我提问。

目录
相关文章
|
10月前
|
API C++ Windows
Visual C++运行库、.NET Framework和DirectX运行库的作用及常见问题解决方案,涵盖MSVCP140.dll丢失、0xc000007b错误等典型故障的修复方法
本文介绍Visual C++运行库、.NET Framework和DirectX运行库的作用及常见问题解决方案,涵盖MSVCP140.dll丢失、0xc000007b错误等典型故障的修复方法,提供官方下载链接与系统修复工具使用指南。
2056 2
|
10月前
|
缓存 算法 程序员
C++STL底层原理:探秘标准模板库的内部机制
🌟蒋星熠Jaxonic带你深入STL底层:从容器内存管理到红黑树、哈希表,剖析迭代器、算法与分配器核心机制,揭秘C++标准库的高效设计哲学与性能优化实践。
C++STL底层原理:探秘标准模板库的内部机制
|
10月前
|
Ubuntu API C++
C++标准库、Windows API及Ubuntu API的综合应用
总之,C++标准库、Windows API和Ubuntu API的综合应用是一项挑战性较大的任务,需要开发者具备跨平台编程的深入知识和丰富经验。通过合理的架构设计和有效的工具选择,可以在不同的操作系统平台上高效地开发和部署应用程序。
341 11
|
10月前
|
IDE 编译器 开发工具
msvcp100.dll,msvcp120.dll,msvcp140.dll,Microsoft Visual C++ 2015 Redistributable,Visual C++ 运行库安装
MSVC是Windows下C/C++开发核心工具,集成编译器、链接器与调试器,配合Visual Studio使用。其运行时库(如msvcp140.dll)为程序提供基础函数支持,常因缺失导致软件无法运行。通过安装对应版本的Microsoft Visual C++ Redistributable可解决此类问题,广泛应用于桌面软件、游戏及系统级开发。
1143 2
|
11月前
|
并行计算 C++ Windows
|
存储 算法 安全
c++模板进阶操作——非类型模板参数、模板的特化以及模板的分离编译
在 C++ 中,仿函数(Functor)是指重载了函数调用运算符()的对象。仿函数可以像普通函数一样被调用,但它们实际上是对象,可以携带状态并具有更多功能。与普通函数相比,仿函数具有更强的灵活性和可扩展性。仿函数通常通过定义一个包含operator()的类来实现。public:// 重载函数调用运算符Add add;// 创建 Add 类的对象// 使用仿函数return 0;
352 0
|
编译器 C++ 开发者
【C++篇】深度解析类与对象(下)
在上一篇博客中,我们学习了C++的基础类与对象概念,包括类的定义、对象的使用和构造函数的作用。在这一篇,我们将深入探讨C++类的一些重要特性,如构造函数的高级用法、类型转换、static成员、友元、内部类、匿名对象,以及对象拷贝优化等。这些内容可以帮助你更好地理解和应用面向对象编程的核心理念,提升代码的健壮性、灵活性和可维护性。
|
编译器 C++ 容器
【c++11】c++11新特性(上)(列表初始化、右值引用和移动语义、类的新默认成员函数、lambda表达式)
C++11为C++带来了革命性变化,引入了列表初始化、右值引用、移动语义、类的新默认成员函数和lambda表达式等特性。列表初始化统一了对象初始化方式,initializer_list简化了容器多元素初始化;右值引用和移动语义优化了资源管理,减少拷贝开销;类新增移动构造和移动赋值函数提升性能;lambda表达式提供匿名函数对象,增强代码简洁性和灵活性。这些特性共同推动了现代C++编程的发展,提升了开发效率与程序性能。
590 12
|
编译器 C语言 C++
类和对象的简述(c++篇)
类和对象的简述(c++篇)