顺序容器定义
该类型的容器中的顺序不依赖于元素的值,而是与元素加入容器时的位置相对应。
顺序容器类型
类型 | 说明 |
---|---|
vector | 可变大小数组。支持随机访问。在尾部之外的位置插入或者删除元素可能较慢。 |
deque | 双端队列。支持快速随机访问。在头尾位置插入、删除元素速度很快。 |
list | 双向链表。只支持双向顺序访问。在list中任何位置进行插入、删除操作速度都很快。 |
forward_list | 单向链表,只支持单向顺序访问。在链表任何位置进行插入、删除元素速度都很快。 |
array | 固定大小数组,支持快速随机访问,不能添加或者删除元素。 |
string | 用于专门保存字符的类似vector容器,随机访问快,在尾部插入、删除元素速度快。 |
问题1:
如何选择顺序容器类型?
(1)通常,使用vector作为基本容器选择。
(2)一般情况下,应用占主导地位的操作(执行的访问操作更多还是插入、删除更多)决定了容器类型的选择。
迭代器
标准容器类型上的所有迭代器都允许我们访问容器中的元素,而所有的迭代器都是通过解引用运算符来实现这个操作。
迭代器范围
迭代器范围是标准库的基础。
问题2
构成迭代器范围的迭代器有何限制?
一般采用左闭合区间[begin,end]表示范围自begin 开始,于end之前结束。迭代器begin 和end必须指向相同的容器,end 可以与begin 指向相同的位置,但不能指向begin之前的位置。
Begin 和end 成员
Begin 和end 的操作生成指向容器中第一个元素和尾元素之后位置的迭代器。这两个迭代器最常见的用途是形成一个包含容器中所有元素的迭代器范围。
Begin 和end 有多个版本:
带r的版本返回反向迭代器
带c开头的版本则返回const 迭代器
带cr的版本则返回const –反向迭代器
示例代码:
vector<int> v1;
const vector<int> v2;
auto it1 = v1.begin(); //it1的类型是vector<int>::iterator
auto it2 = v2.begin(); //it2的类型是vector<int>::const_iterator
auto it3 = v1.cbegin(); //it3的类型是vector<int>::const_iterator
auto it4 = v2.cbegin(); //it3的类型是vector<int>::const_iterator
表面看到的类型是在这样,我们可以看底层源码:
(1)it1的类型
auto it1 = v1.begin(); //it1的类型是vector<int>::iterator
begin () 的源码如下:
iterator begin() _NOEXCEPT
{ // return iterator for beginning of mutable sequence
return (iterator(this->_Myfirst(), &this->_Get_data()));
}
(2)it2的类型
auto it2 = v2.begin(); //it2的类型是vector<int>::const_iterator
begin() 的源码如下:
const_iterator begin() const _NOEXCEPT
{ // return iterator for beginning of nonmutable sequence
return (const_iterator(this->_Myfirst(), &this->_Get_data()));
}
(3)it3的类型
auto it3 = v1.cbegin(); //it3的类型是vector<int>::const_iterator
cbegin() 的源码如下:
const_iterator cbegin() const _NOEXCEPT
{ // return iterator for beginning of nonmutable sequence
return (begin());
}
把一个普通对象强转成常对象
(4)it4的类型
auto it4 = v2.cbegin(); //it3的类型是vector<int>::const_iterator
cbegin() 的源码
const_iterator cbegin() const _NOEXCEPT
{ // return iterator for beginning of nonmutable sequence
return (begin());
}
容器定义和初始化
注意事项:
将一个容器初始化为另一个容器的拷贝有两种方法:一是可以直接拷贝整个容器,或者拷贝由一个迭代器对指定的元素范围。
当将一个容器初始化为另一个容器的拷贝时,两个容器的容器类型和元素类型都必须相同。
拷贝由一个迭代器对指定的元素范围无限制,只要迭代器所指的元素可以转换即可。
赋值和swap
使用swap() 函数来交换对象中的元素
vector<int> v1;
vector<int> v6;
v6.swap(v1); //对象调用swap()函数,参数传递
swap(v1, v6);
使用assign(仅顺序容器)
assign 允许我们从一个不同但相容的类型赋值,或者从容器的一个资讯列赋值。assign 操作用参数指定的元素(的拷贝)替换左边容器中的所有元素。
list<string> names;
vector<const char *> oldstyle;
names = oldstyle; //错误:容器类型不匹配
names.assign(oldstyle.begin(), oldstyle.end());