9.1.1
将一个容器复制给另一个容器时,类型必须匹配:容器类型和元素类型都必须相同。
使用迭代器时,不要求容器类型相同。容器内的元素类型也可以不相同,只要它们相互兼容,能够将要复制的元素转换为所构建的新容器的元素类型,即可实现复制。
不提供元素初始化式时, 标准库将为该容器实现值初始化(3.3.1节)。采用这种类型的初始化,元素类型必须是内置或复合类型,或者是提供了默认构造函数的类类型。如果元素类型没有默认构造函数,则必须显式指定其元素初始化式。
9.1.2
容器元素类型必须满足以下两个约束:• 元素类型必须支持赋值运算。
• 元素类型的对象必须可以复制。
大多数类型满足上述最低限度的元素类型要求。除了引用类型外,所有内置或复合类型都可用做元素类型。引用不支持一般意义的赋值运算,因此没有元素是引用类型的容器。
注意,在指定容器元素为容器类型时,必须如下使用空格:
vector< vector<string> > lines; // ok: space required between close>
vector< vector<string>> lines; // error: >> treated as shift operator
必须用空格隔开两个相邻的 > 符号,以示这是两个分开的符号,否则,系统会认为 >> 是单个符号,为右移操作符,并导致编译时错误。
9.2
vector 和 deque 容器的迭代器提供额外的运算 :
在迭代器上加(减)整数值 n,将产生指向容器中前面(后面)第 n 个元素的迭代器
这里迭代器加减法的复合赋值运算:将 iter1 加上或减去 iter2 的 运算结果赋给 iter1
两个迭代器的减法,其运算结果加上右边的迭代器即得左边的迭代器。这两个迭代器必须指向同一个容器中的元素或超出容器末端的下一位置
迭代器的关系操作符。当一个迭代器指向的元素在容器中位于另一个迭代器指向的元素之前,则前一个迭代器小于后一个迭代器。关系操作符的两个迭代器必须指向同一个容器中的元素或超出容器末端的下一位置
两个迭代器的减法,其运算结果加上右边的迭代器即得左边的迭代器。这两个迭代器必须指向同一个容器中的元素或超出容器末端的下一位置
迭代器的关系操作符。当一个迭代器指向的元素在容器中位于另一个迭代器指向的元素之前,则前一个迭代器小于后一个迭代器。关系操作符的两个迭代器必须指向同一个容器中的元素或超出容器末端的下一位置
9.3.3
push_back 函数会在容器 container 尾部创建一个新元素 , 而 container 的类型则可能是 list、vector 或 deque。除了 push_back(pop_back) 运算,list 和 deque 容器类型还提供了类似的操作:push_front(pop_front)。
容器元素都是副本
在容器中添加元素时,系统是将元素值复制到容器里。类似地,使用一段元素初始化新容器时,新容器存放的是原始元素的副本。被复制的原始值与新容器中的元素各不相关,此后,容器内元素值发生变化时,被复制的原值不会受到影响,反之亦然。insert 操作则提供了一组更通用的插入方法 :
c.insert(p,t) | 在迭代器 p 所指向的元素前面插入值为 t 的新元素。返回指向新添加元素的迭代器 |
c.insert(p,n,t) | 在迭代器 p 所指向的元素前面插入 n 个值为 t 的新元素。 返回 void 类型 |
c.insert(p,b,e) | 在迭代器 p 所指向的元素前面插入由迭代器 b 和 e 标记 的范围内的元素。返回 void 类型 |
要重新加载整个容器,指向新插入元素后面的那个元素的迭代器也会失效。 任何 insert 或 push 操作都可能导致迭代器失效。当编写循环将元素插入到 vector 或 deque 容器中时,程序必须确保迭代器在每次循环后都得到更新。
避免存储 end 操作返回的迭代器
在容器的任何位置插入任何元素都会使该end迭代器失效。
vector<int>::iterator first = v.begin(),
last = v.end(); // cache end iterator
// diaster: behavior of this loop is undefined
while (first != last) {
// do some processing
// insert new value and reassign first, which otherwise would be invalid
first = v.insert(first, 42);
++first; // advance first just past the element we added
}
上述代码的行为未定义。在很多实现中,该段代码将导致死循环。问题在于这个程序将 end 操作返回的迭代器值存储在名为 last 的局部变量中。循环体中实现了元素的添加运算,添加元素会使得存储在 last 中的迭代器失效。该迭代器既没有指向容器 v 的元素,也不再指向 v 的超出末端的下一位置。
9.3.4
所有的容器类型都支持用关系操作符(第 5.2 节)来实现两个容器的比较。显比较的容器必须具有相同的容器类型,而且其元素类型也必须相同。9.3.7
c.erase(b,e) | 删除迭代器 b 和 e 所标记的范围内所有的元素 返回一个迭代器,它指向被删除元素段后面的元素。如果 e 本 身就是指向超出末端的下一位置的迭代器,则返回的迭代器也 指向容器的超出末端的下一位置 |
c.erase(p) | 删除迭代器 p 所指向的元素 返回一个迭代器,它指向被删除元素后面的元素。如果 p 指向 容器内的最后一个元素,则返回的迭代器指向容器的超出末端 的下一位置。如果 p 本身就是指向超出末端的下一位置的迭代 器,则该函数未定义 |
9.3.8
assign 操作首先删除容器中所有的元素,然后将其参数所指定的新元素插入到该容器中。与复制容器元素的构造函数一样,如果两个容器类型相同,其元素类型也相同,就可以使用赋值操作符(=)将一个容器赋值给另一个容器。如果在不同(或相同)类型的容器内,元素类型不相同但是相互兼容,则其赋值运算必须使用 assign 函数。swap 操作实现交换两个容器内所有元素的功能。要交换的容器的类型必须匹配:操作数必须是相同类型的容器,而且所存储的元素类型也必须相同。
赋值和 assign 操作使左操作数容器的所有迭代器失效。swap操作则不会使迭代器失效。完成 swap 操作后,尽管被交换的
元素已经存放在另一容器中,但迭代器仍然指向相同的元素。
元素已经存放在另一容器中,但迭代器仍然指向相同的元素。
9.5
vector 和 deque容器提供了对元素的快速随机访问,但付出的代价是,在容器的任意位置插入或删除元素,比在容器尾部插入和删除的开销更大。list 类型在任何位置都能快速插入和删除,但付出的代价是元素的随机访问开销较大。• 与 vector 容器一样, 在 deque 容器的中间 insert 或 erase 元素效率比较低。
• 不同于 vector 容器,deque 容器提供高效地在其首部实现 insert 和erase 的操作,就像在容器尾部的一样。
• 与 vector 容器一样而不同于 list 容器的是, deque 容器支持对所有元素的随机访问。
• 在 deque 容器首部或尾部插入元素不会使任何迭代器失效,而首部或尾部删除元素则只会使指向被删除元素的迭代器失效。在 deque 容器的任何其他位置的插入和删除操作将使指向该容器元素的所有迭代器都失效。
9.6.3
使用 substr 操作可在指定 string 对象中检索需要的子串。
string s("hello world");
// return substring of 5 characters starting at position 6
string s2 = s.substr(6, 5); // s2 = world