C++ Primer学习纪录(四)标准库vector容器

STLvector容器简介

模板

先介绍下模板,C++语言中既有类模板,也有函数模板STL中大量使用了类模板编程,这次学习的vector容器也自然是类模板之一。
模板的编写等学到了再做详细介绍。模板本身不是类或函数,而是可以看作一份类或函数的编写说明书,编译器通过这份说明书在编译时正确生成相关的类或函数,这一过程称为实例化

定义和初始化vector对象

vector使用之前,需要包含vector的头文件,include <vector>, 并且可以使用std::vector<T>来使用,当然也可以使用using namespace std::vector来简化代码。

由于vector使用了类模板编程,因此vector可以容纳绝大多数的类型对象作为其元素,但引用除外(引用不是对象)。

C++11之前,若用vector作为vector的对象,则需要再最后的尖括号之间留出一个空格, 例如vector<vector<int> >, 但C++11标准以后不需要流出哪一个空格。

具体如何初始化见下图,T为任意类型对象。
在这里插入图片描述

列表初始化

列表初始化是C++11标准所引入的对象初始化方法,用花括号括起来的初试元素值来初始化对象。

vector<int> number = {0, 10, 50};
vector<int> number{0, 10, 50};

上述代码中
第一句话number包含了3个元素,为0, 10, 50, 该操作为拷贝初始化;
第二句话与第一句同样的效果,但其初始化方式为直接初始化。

在C++11中,若使用2个元素的列表初始化,当元素与容器内数据类型不同时,会执行列表初始化失败,但程序不会报错,而是尝试进行默认初始化

vector<int> v1{10, 1};
vector<string> v2{10, 1}; 
vector<string> v3{10, 1, 20};

上述代码
第一句为列表初始化,v1中含有101两个元素;
第二句话101不是string类型,因此进行列表初始化失败,编译器尝试默认初始化,因此与vector<string> v2(10, 1)效果相同;
第三句话同样列表初始化失败,但与2不同的时,当编译器进行默认初始化时也失败,因此出错。

push_back操作

vector容器又称为动态数组,动态性体现在可以通过push_back操作向尾部压入一个元素。

vector<int> v;
for(int i = 0; i < 100; ++i){
	v.push_back(i);
}

上述代码像一个空vector容器中添加了0~99100个数。

请注意若循环体内有push_back操作,不要使用范围for语句,因为push_back会使当前的迭代器失效。
例如

vector<int> v{0, 1, 2, 3, 4};
for(auto it: v){
	v.push_back(10);
}

这样的代码是完全错误的。

vector的其他操作

在这里插入图片描述
其中比较操作符与string类的比较操作符相同,也是通过字典序来进行比较。

字典序比较:
对于序列< a 1 a_{1} a1, a 2 a_{2} a2, a 3 a_{3} a3 a n a_{n} an…> 和 < b 1 b_{1} b1, b 2 b_{2} b2, b 3 b_{3} b3 b n b_{n} bn…>而言,< a 1 a_{1} a1, a 2 a_{2} a2, a 3 a_{3} a3 a n a_{n} an…>小于< b 1 b_{1} b1, b 2 b_{2} b2, b 3 b_{3} b3 b n b_{n} bn…>是指:
存在下标m, 使得 a 1 a_{1} a1 = b 1 b_{1} b1, a 2 a_{2} a2 = b 2 b_{2} b2 a m a_{m} am = b m b_{m} bm, a m + 1 a_{m+1} am+1 < b m + 1 b_{m + 1} bm+1… (后续的随意)

唯一一点的区别是必须要保证vector中的元素可以进行比较(有一些自己定义的类/结构体没有定义过比较操作,无法进行比较)

size()返回的依旧是size_type类型,因此建议使用auto len = v.size()

索引操作

vector的索引与数组类似,索引范围均为[0, length)的左闭右开区间。只有一点要注意,就是不要通过索引操作为vector添加元素。

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

v是空的,通过下标添加会报错,正确的做法是通过push_back添加元素。
当然索引操作是可以修改元素的~ 除非定义为const vector<T>类型

迭代器操作

STL标准库的容器/对象均拥有名为beginend的成员。begin方法返回第一个元素的迭代器,end方法返回最后一个元素后面一个位置的迭代器。基于这个特性,可以使用v.begin() == v.end()来判断一个容器/对象是否为空。

迭代器运算

迭代器可以通过一些运算符来进行运算,具体如下
在这里插入图片描述
这儿解释*解引用符和->成员访问操作符
*类似于指针中的解引用,可以解引用迭代器,获取迭代器所指向的对象。若该对象是一个类,可以使用.访问其中的成员。
->箭头运算符将解引用和成员访问两个操作结合在一起。it->empty()(*it).empty()是一个效果。

注意(*it)要加括号,因为*it.empty()是指对it.empty()进行解引用,而不是对it迭代器进行解引用。

vectorstring特有的迭代器操作

在这里插入图片描述
这些操作是在setmap等其他容器的迭代器中所没有的。

因此在使用迭代器操作时,建议使用!===操作
例如for(auto it = v.begin(); it != v.end(); it++){...};

iter1 - iter2返回的类型是difference_type类型,是带符号整数。引入目的与size_type相同,因此建议使用auto diff = iter1 - iter2;

const_iteratoriterator

const_iterartor与常量指针差不多,能读但不能修改指向对象的值。iterator与指针类似,能读能写。若定义const vector<T> name常量对象,则name.begin()返回一个const_iterator; 若定义为非常量对象, 则返回一个iterator

在非常量对象的vector中若希望使用const_iterator, 可以使用name.cbegin()或者name.cend()来进行获取。但常量对象的容器不能使用iterator

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值