C++Primer_2021.11.8

2021.11.8
标准库就是武器库、功法招式。
第三章:字符串、向量和数组
标准库类型:
string
vector
迭代器:它是string和vector的配套类型,常被用于访问string中的字符或vector中的元素。

标准库类型vector
vector表示对象的集合,其中所有对象的类型相同。集合中的每个对象都有一个与之对应的索引,用于访问对象。因为vector“容纳着”其它对象,所以常被称为容器(container)。

vector::iterator it; // 能读写
string::iterator it2; // 能读写
vector::const_iterator it3;// 只能读
string::const_iterator it4; // 只能读
begin和end返回的具体类型由对象是否是常量决定。若是常量返回const_iterator,若对象不是常量,返回iterator。
为了便于专门得到const_iterator类型的返回值,c++11新标准引入两个新函数,分别是cbegin和cend

解引用迭代器可获得迭代器所指对象。注意,迭代器解引用必须使用括号括起来。
箭头运算符把解引用和成员访问两个操作结合在一起。也就是说:
it->mem和(*it).mem表达相同的意思。

使用迭代器运算的一个经典算法时二分搜索。二分搜索从有序序列中寻找某个给定的值。
二分搜索可以认为是切分,那么切分到单元长时,就是终止条件。此时,所切分的长度就是n*(1/pow(2,x))= 1 => x = logn。即所需要的执行代码的条数,即时间大O。

在二分搜索程序中,为什么用mid = beg + (end - beg) / 2,而非mid = (beg + end) / 2;?是因为end-beg定义了迭代器的距离,而两个迭代器相加的操作并没有定义,所以不能用。但定义了一个迭代器+(或-)的操作。

3.5数组:
与vector不同的地方是,数组的大小确定不变,不能随意想数组中添加元素。因为数组大小固定,因此对某些特殊的应用来说,程序的运行性能较好,但相应地也损失一些灵活性。

3.5.1定义和初始化内置数组
数组的声明形如:a[d],其中a是数组名字,d是数组的维度。
维度必须是一个常量表达式。

unsigned cnt = 42; 不是常量表达式
constexpr unsigned sz = 42; 是常量表达式

int arr[10]; // 含有10个整数的数组;
int* parr[sz]; // 含有42个整型指针的数组;

string bad[cnt]; // 错误
string strs[get_size()]; // 当get_size是constexpr时正确,否则错误。

默认情况下,数组的元素被默认初始化。

warning:和内置类型的变量一样,若在函数内部定义了某种内置类型的数组,那么默认初始化会令数组含有未定义的值。

定义数组时必须制定数组的类型,不允许使用auto关键字由初始值的列表推断类型。另外和vector一样,数组的元素应为对象,因此不存在引用的数组;
显示初始化数组元素,若提供的维度大于初始值个数,剩下的元素被初始化成默认值。

字符数组的特殊性:
一定要注意字符串字面值的结尾处还有一个空字符,这个空字符也会像字符串的其它字符一样被拷贝到字符数组中去。若结尾已有显示的空字符'\0',则不再添加。

数组不允许拷贝和赋值:
不能将数组的内容拷贝给其他数组作为其初始值,也不能用数组为其他数组赋值。

理解复杂的数组声明:
数组能放大多数类型的对象,如:
定义存放指针的数组比较简单和直接
但定义数组的指针或数组的引用就稍微赋值一点:
int ptrs[10];
int &refs[10] = /
?/; 错误:不存在引用的数组
int (
Parray)[10] = &arr; // Parray指向一个含有10个整数的数组
int (&arrRef)[10] = arr; // arrRef引用一个含有10个整数的数组。

默认情况下,类型修饰符从右向左依次绑定。对于ptrs来说,从从右往左理解含义比较简单:首先知道定义一个大小为10的数组,它的名字是ptrs,数组中存放的是指向int的指针。

而对于Parray,需要由内向外阅读,再从右到左阅读。首先,圆括号部分是,*Parray意味着Parray是一个指针,接下来观察右边,可知道是指向大小为10的数组的指针,最后观察左边,知道数组中的元素是int。同理,(&arrRef),表示arrRef是一个引用。当然,对修饰符的数量并没有特殊的限制,如:
int *(&arry)[10] = ptrs; // arry是数组的引用,该数组有10个指针。

tip:要理解数组声明的含义,最好的办法是从数组的名字开始,按照由内往外的顺序阅读。

Q:相比vector,数组有哪些缺点?
数组和vector一样可以存放任意对象,
1.维度必须是一个常量表达式,意味着无法动态增加元素,容易产生内存浪费;
2.不允许拷贝和赋值;而vector允许拷贝和赋值。数组可通过循环一个元素一个元素进行拷贝和赋值。
3.使用过程中容易发生数组越界,而vector可使用更多机制来控制,如使用迭代器。
4.灵活性差,如添加删除元素,获取长度,而vector通过push_back,erase或pop删除元素;size获得长度等
5.数组的数组。每一个作为元素的数组,长度必须一致。如:arr[3][2]是一个含3个容量为2的数组的数组,这3个数组的容量必须一致,才能存放进同一个数组中。

而vector<vector>类型的vector,其存放进去的vector对象容量任意,可以为0。

3.5.2访问数组元素
使用for语句或下标运算符来访问
使用数组下标时,通常将其定义为size_t类型。size_t是一种机器相关的无符号类型,被设计的足够大以便能表示内存中任意对象的大小。在cstddef头文件中定义了该类型。是c标准库stddef.h头文件的c++语言版本。

原文地址:https://www.cnblogs.com/gwzz/p/15525698.html