C++ Primer 中文版 学习笔记(八)

第9章  顺序容器

1  接受容器大小做形参的构造函数只适用于顺序容器,而关联容器不支持这种初始化。

2  容器内元素类型的约束:

1)  元素类型必须支持赋值运算。(支持赋值

2)  元素类型的对象必须可以复制。(可以复制

IO库类型不支持复制或赋值。因此,不能创建存放IO类型对象的容器。

3  vector和deque容器的迭代器提供额外的运算。(算数运算以及除 == 和 != 的关系操作符)

1)      关系操作符只适用于vectordeque容器,这是因为只有这两种容器为其元素提供快速、随机的访问。

2)      List容器的迭代器既不支持算数运算,也不支持关系运算。它只提供前置和后置的自增、自减运算以及相等(不等)运算。

4  对形成迭代器范围的迭代器的要求:

1)  它们指向同一个容器中的元素或超出末端的下一位置。

2)  如果这两个迭代器不相等,则对first反复做自增运算必须能够到达last,换句话说,在容器中,last绝对不能位于first之前。

5  编译器无法知道迭代器所关联的是哪个容器,也无法检测迭代器是否失效(自己注意更新迭代器)。

容器元素都是副本。在容器中添加元素时,系统是将元素值复制到容器里。容器内元素值发生变化时,被复制的原值不会受到影响,反之亦然。

如同其他操作一样,erase操作也不会检查它的参数。程序员必须确保用作参数的迭代器或迭代器范围是有效的。erase返回一个指向被删除元素或元素段后面的元素。

赋值和assign操作使左操作数容器的所有迭代器失效。

   swap操作则不会使迭代器失效。完成swap操作后,尽管被交换的元素已经存放在另一容器中,但迭代器仍然指向相同的元素。

   该操作不会删除或插入任何元素,而且保证在常量时间内实现交换。由于容器内没有移动任何元素,因此迭代器不会失效。

首先,vector内部是维护一个动态数组,大概样子是这样:
class vector
{
    T* begin;
    T* finish;
    T* capacity;
};
vector::iterator虽说不一定是用指针实现,但是一定保存了数组中元素的真实内存地址(其实也不是一定,实现也可以保存begin和偏移量,但这么做明显太复杂,实际中都是直接保存元素地址的)。
vector整个swap的时候,其实交换的是双方begin, finish, capacity这三个指针的值。在这个过程中,所有从该vector创建的iterator本身都不会发生任何改变(打个比方就是你换一个手机号,那些存了你以前手机号的人手头的电话号码并不会随之发生改变,除非你告诉他们)。因为iterator没有改变,所以你打印iterator本身的地址时,得到的仍旧是原来的值。另外,动态数组本身并没有被销毁,只是改变了所属。所以实际两个vector中所有元素的物理地址都没有改变,iterator指向的依然是原来的元素。

9  vector容器的内存分配策略:以最小的代价连续存储元素。由此而带来的访问元素的便利弥补了其存储代价。

没有更多推荐了,返回首页