博客
关于我
C++标准库:容器库概览
阅读量:327 次
发布时间:2019-03-04

本文共 3660 字,大约阅读时间需要 12 分钟。

本文为《C++ Primer》的读书笔记

目录

  • 一般来说, 每个容器都定义在一个头文件中, 文件名与类型名相同。即, deque定义在头文件deque中… 容器均定义为模板类,需要额外提供元素类型信息:
list
deque

不要尝试继承一个 标准容器 / string

  • E f f e c t i v e   C + + Effective\ C++ Effective C++:所有的 STL 容器都未被设计为作为基类来使用,因此它们都没有定义虚析构函数;这样如果你用基类指针指向动态分配的派生类对象并 delete 该指针就会导致资源泄漏!

对容器可以保存的元素类型的限制

  • 顺序容器几乎可以保存任意类型的元素。特别是, 我们可以定义一个容器, 其元素的类型是另一个容器
  • 某些容器操作对元素类型有其自己的特殊要求。我们可以为不支持特定操作需求的类型定义容器, 但这种情况下就只能使用那些没有特殊要求的容器操作了
    • 例如, 顺序容器构造函数的一个版本接受容器大小参数,它使用了元素类型的默认构造函数。但某些类没有默认构造函数。我们可以定义一个保存这种类型对象的容器, 但我们在构造这种容器时不能只传递给它一个元素数目参数:
// 假定 noDefault 是一个没有默认构造函数的类型vector
v1(10, init); // 正确:提供了元素初始化器vector
v2(10); // 错误: 必须提供一个元素初始化器

容器类型成员

在这里插入图片描述

这些元素相关的类型别名在泛型编程中非常有用:

// iter是通过list
定义的一个迭代器类型list
::iterator iter;// count是通过vector
定义的一个difference_type 类型vector
::difference_type count;

获取迭代器

在这里插入图片描述

  • 大多数容器还提供反向迭代器用于反向遍历容器。与正向迭代器相比,各种操作的含义也都发生了颠倒。例如,对一个反向迭代器执行++操作,会得到上一个元素:

在这里插入图片描述

可以将一个普通的iterator转换为对应的const_iterator, 但反之不行

auto it7 = a.begin(); 	// 仅当a是const时, it7是const_iteratorauto it8 = a.cbegin(); 	// it8是const_iterator

当不需要写访问时, 应使用cbegincend

容器定义和初始化

默认构造函数

在这里插入图片描述

将一个容器初始化为另一个容器的拷贝

  • 直接拷贝整个容器 (两个容器的类型及其元素类型必须匹配)

在这里插入图片描述

  • (array除外)拷贝由一个迭代器对指定的元素范围
    (不要求容器类型相同。而且, 新容器和原容器中的元素类型也可以不同, 只要能将要拷贝的元素转换为要初始化的容器的元素类型即可)

在这里插入图片描述

list
authors = { "Milton", "Shakespeare", "Austen"};vector
articles = { "a", "an", "the"};list
list2(authors); //正确: 类型匹配deque
authList(authors); //错误:容器类型不匹配// 正确: 可以将const char* 元素转换为stringforward_list
words(articles.begin(), articles.end());

由于两个迭代器表示一个范围, 因此可以使用这种构造函数来拷贝一个容器中的子序列。例如, 假定迭代器it表示authors中的一个元素, 我们可以编写如下代码

// 拷贝元素, 直到(但不包括) it指向的元素deque
authList(authors.begin(), it);

列表初始化

在这里插入图片描述

list
authors = { "Milton", "Shakespeare", "Austen"};

与顺序容器大小相关的构造函数

关联容器并不支持

在这里插入图片描述

vector
ivec(10, -1);forward_list
ivec(10); // 10个元素, 每个都初始化为0

如果元素类型是内置类型或者是具有默认构造函数的类类型,可以只为构造函数提供一个容器大小参数。如果元素类型没有默认构造函数,除了大小参数外,还必须指定一个显式的元素初始值

赋值和swap

赋值相关运算可能会导致指向左边容器内部的迭代器、引用和指针失效

赋值运算符

在这里插入图片描述

array
a1 = { 0,1,2,3,4,5,6,7,8,9};array
a2 = { 0}; a1 = a2; // 替换a1中的元素a2 = { 0}; // 错误: 不能将一个花括号列表赋予数组

由于右边运算对象的大小可能与左边运算对象的大小不同, 因此 array类型不支持assign,也不允许用花括号包围的值列表进行赋值

使用assign (仅顺序容器)

在这里插入图片描述

  • assign 成员允许我们从一个不同但相容的类型赋值, 或者从容器的一个子序列赋值
  • assign操作用参数所指定的元素(的拷贝)替换左边容器中的所有元素

例如, 我们可以用assgin实现将一个vector中的一段char*值赋予一个list中的string:

list
names;vector
oldstyle;names = oldstyle; //错误:容器类型不匹配//正确: 可以将const char* 转换为stringnames.assign(oldstyle.cbegin(), oldstyle.cend());

由于其旧元素被替换,因此传递给assign的迭代器不能指向调用assign的容器

// 等价于slist1.clear();// 后跟slist1.insert(slist1.begin(), 10, "Hiya!");list
slistl(1); // 1个元素, 为空stringslist1.assign(10, "Hiya!"); // 10 个元素, 每个都是"Hiya!"

swap

在这里插入图片描述

在新标准库中, 容器既提供成员函数版本的swap, 也提供非成员版本的swap。而早期标准库版本只提供成员函数版本的swap。非成员版本的swap在泛型编程中是非常重要的。统—使用非成员版本的swap是一个好习惯

vector
svec1(10); // 10 个元素的vectorvector
svec2(24); // 24 个元素的vectorswap(svec1, svec2); // `svec1`将包含24个`string`元素,`svec2`将包含10个`string`

array外, 交换两个容器内容的操作保证会很快——元素本身并未交换, swap只是交换了两个容器的内部数据结构


元素不会被移动的事实意味着,

  • string外, 指向容器的迭代器、引用和指针在swap操作之后都不会失效。它们仍指向swap操作之前所指向的那些元素。但是,在swap之后, 这些元素已经属于不同的容器了

  • 对一个string调用swap会导致迭代器、引用和指针失效

  • swap 两个array会真正交换它们的元素。因此, arrayswap操作之后,指针、引用和迭代器所绑定的元素保持不变

容器大小操作

除了forward_list,每个容器类型都有三个与大小相关的操作

在这里插入图片描述

关系运算符

在这里插入图片描述

关系运算符左右两边的运算对象必须是相同类型的容器,且必须保存相同类型的元素

比较两个容器实际上是进行元素的逐对比较。这些运算符的工作方式与string 的关系运算类似:

  • 如果两个容器具有相同大小且所有元素都两两对应相等, 则这两个容器相等;否则两个容器不等
  • 如果两个容器大小不同,但较小容器中每个元素都等于较大容器中的对应元素, 则较小容器小于较大容器。
  • 如果两个容器都不是另一个容器的前缀子序列,则它们的比较结果取决于第一个不相等的元素的比较结果。

只有当其元素类型也定义了相应的比较运算符时,我们才可以使用关系运算符来比较两个容器(容器的关系运算符使用元素的关系运算符完成比较)

转载地址:http://iqih.baihongyu.com/

你可能感兴趣的文章
mysql5.7命令总结
查看>>
mysql5.7安装
查看>>
mysql5.7性能调优my.ini
查看>>
MySQL5.7新增Performance Schema表
查看>>
Mysql5.7深入学习 1.MySQL 5.7 中的新增功能
查看>>
Webpack 之 basic chunk graph
查看>>
Mysql5.7版本单机版my.cnf配置文件
查看>>
mysql5.7的安装和Navicat的安装
查看>>
mysql5.7示例数据库_Linux MySQL5.7多实例数据库配置
查看>>
Mysql8 数据库安装及主从配置 | Spring Cloud 2
查看>>
mysql8 配置文件配置group 问题 sql语句group不能使用报错解决 mysql8.X版本的my.cnf配置文件 my.cnf文件 能够使用的my.cnf配置文件
查看>>
MySQL8.0.29启动报错Different lower_case_table_names settings for server (‘0‘) and data dictionary (‘1‘)
查看>>
MYSQL8.0以上忘记root密码
查看>>
Mysql8.0以上重置初始密码的方法
查看>>
mysql8.0新特性-自增变量的持久化
查看>>
Mysql8.0注意url变更写法
查看>>
Mysql8.0的特性
查看>>
MySQL8修改密码报错ERROR 1819 (HY000): Your password does not satisfy the current policy requirements
查看>>
MySQL8修改密码的方法
查看>>
Mysql8在Centos上安装后忘记root密码如何重新设置
查看>>