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)


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


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


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


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


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

目录
相关文章
|
9天前
|
存储 程序员 C语言
c++primer plus 6 读书笔记 第四章 复合类型
c++primer plus 6 读书笔记 第四章 复合类型
|
2天前
|
存储 算法 C++
C++一分钟之-容器概览:vector, list, deque
【6月更文挑战第21天】STL中的`vector`是动态数组,适合随机访问,但插入删除非末尾元素较慢;`list`是双向链表,插入删除快但随机访问效率低;`deque`结合两者优点,支持快速双端操作。选择容器要考虑操作频率、内存占用和性能需求。注意预分配容量以减少`vector`的内存重分配,使用迭代器而非索引操作`list`,并利用`deque`的两端优势。理解容器内部机制和应用场景是优化C++程序的关键。
18 5
|
2天前
|
存储 算法 C++
C++一分钟之-标准模板库(STL)简介
【6月更文挑战第21天】C++ STL是高效通用的算法和数据结构集,简化编程任务。核心包括容器(如vector、list)、迭代器、算法(如sort、find)和适配器。常见问题涉及内存泄漏、迭代器失效、效率和算法误用。通过示例展示了如何排序、遍历和查找元素。掌握STL能提升效率,学习过程需注意常见陷阱。
20 4
|
16小时前
|
安全 程序员 C++
C++中的类型查询:探索typeid和type_info
C++中的类型查询:探索typeid和type_info
7 1
|
2天前
|
存储 编译器 程序员
C++一分钟之-auto关键字与类型推导
【6月更文挑战第21天】`auto`在C++11中重生,简化了类型声明,尤其在处理复杂类型时。它让编译器根据初始化值推导变量类型,减少了冗余和错误。使用`auto`简化了迭代器声明和函数返回类型推导,但也带来挑战:类型推导可能不直观,未初始化的`auto`是错误的,且过度使用影响可读性。使用`auto&`和`auto*`明确引用和指针,`decltype`辅助复杂类型推导,保持适度使用以维持代码清晰。
14 1
|
3天前
|
C语言 C++
C++对C的改进和拓展\string类型
C++对C的改进和拓展\string类型
5 1
|
9天前
|
编译器 C++
C++学习笔记(二开始学习C++)
C++学习笔记(二开始学习C++)
|
8天前
|
存储 算法 程序员
【C++进阶】深入STL之vector:构建高效C++程序的基石
【C++进阶】深入STL之vector:构建高效C++程序的基石
13 1
|
8天前
|
编译器 C++ 容器
【C++进阶】深入STL之vector:深入研究迭代器失效及拷贝问题
【C++进阶】深入STL之vector:深入研究迭代器失效及拷贝问题
14 0
|
9天前
|
大数据 C++ 索引
C++ STL标准库 《vector向量原理与实战分析》
C++ STL标准库 《vector向量原理与实战分析》
11 0