C++---CHAPTER 9: CONTAINER

  • 顺序容器
vector 尾部之外的位置插入或删除元素可能很慢
deque 头尾位置插入、删除速度很快
list 任何位置插入、删除速度很快
forward_list 只支持单向顺序访问,任何位置插入、删除都很快。
array 固定大小数组。不能添加删除元素
string 随机访问快、尾部插入删除很快。
  • 容器操作
类型别名
iterator 此容器类型的迭代器类型
const_iterator 读取元素,不能修改元素的迭代器类型
size_type 无符号类型,保存此容器类型的最大可能容器的大小
difference_type 带符号整数类型,两个迭代器之间的距离
value_type 元素类型
reference 元素的左值类型;与value_type&含义相同
const_reference 元素的const左值类型(vonst vlue_type&)
构造函数
C c; 默认构造函数,构造空容器
C c1(c2); 构造c2的拷贝到c1
C c(b,e); 构造c,将接待器b和e范围的元素拷贝到c(不支持array)
C c{a, b, c,...} 列表初始化c
赋值与swap
C1 = c2
C1 = {a, b, c,...}
a.swap(b);swap(a,b) 交换a与b的元素
大小
c.size() c中元素的数目(不支持forward_list)
c.max_size() c可保存的最大元素数目
c.empty()
添加或删除元素 在不同容器中,操作的接口不同
c.insert(args) 将args中的元素拷贝到c
c.emplace(inits) 使用inits构造c中的一个元素
c.erase(args) 删除args指定的元素
c.clear() 删除c中的所有元素,返回void
关系运算符 所有容器都支持:如==、!=
获取迭代器
c.cbegin(),c.cend() 返回const_iterator
reverse_iterator 逆序寻址的迭代器

容器定义和初始化

C seq(n);       // seq包含n个元素,都被值初始化
C seq(n, t);  // seq包含n个值为t的元素
list<string> authors = {"Milton", "Austen"}; //列表初始化
  • notes: 1. 将一个容器初始化为另一个容器的拷贝时,两个容器的容器类型和元素类型都必须相同。
  1. 顺序容器的构造函数才接受大小参数,关联容器并不支持。
  • 标准库 array
    使用array必须指定元素类型和大小:
array<int, 42> // 类型为:保存42个int的数组
 array<int>:: size_type j;  //错误

不能对内置数组类型进行拷贝,但是array类型是可以的:

array<int ,10> digits = {0,1,2,3,4,5,6,7,8,9};
array<int, 10> copy = digits; // right

容器赋值运算

赋值和swap

array<int, 10> a1 = {...};
array<int 10> a2 = {0}; //所有元素均为 0
a2 = {0}; //错误,不能将一个花括号列表赋予数组
// 通常swap比从c2向c1拷贝元素要快
swap(c1,c2);
c1.swap(c2);  

seq.assign(b, e); // 将seq中的元素替换为迭代器b和e所表示的范围的元素,迭代器b、e不能指向seq中的元素
seq.assign(il); // 将seq中的元素替换为初始化列表il中的元素
seq.assign(n,t); // 将seq中的元素替换为n个值为t的元素
  • 警告:赋值相关运算会导致指向左边容器内部的迭代器、引用和指针失效。而swap操作将容器内容交换不会导致指向容器的迭代器、引用和指针失效(array和string除外)。

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

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

向顺序容器添加元素

c.push_back(t) , c.emplace_back(args) c的尾部创建一个值为t或由args创建的元素。
c.insert(p,t) , c.emplace(p,args) 在迭代器p指向的元素之前创建一个值为p或由args创建的元素。
c.insert(p, n , t) 在迭代器p指向的元素之前插入n个值为t的元素。返回新添加的第一个元素的迭代器,若n为0,返回p
c.insert(p, b, e) 将迭代器b、e指定的范围内的元素插入到迭代器p指向的元素之前。b、e不能指向c中的元素。 返回新添加的第一个元素的迭代器,若n为0,返回p
c.insert(p , il) il是一个花括号保卫的元素值列表,将这些值插入到p指向的元素之前。 返回新添加的第一个元素的迭代器,若n为0,返回p
  • insert的返回值
    下面的例子,iter每次都指向新加入元素的位置:
list<string> lst;
auto iter = lst.begin();
while(cin>>word)
  iter = lst.insert(iter, word); //等价于调用 push_front
  • 使用emplace操作
    假设c里保存的是Sales_data成员:
c.emplace_back("970", 25, 15.99);
c.push_back("970", 25, 15.99); //错误,没有接受三个参数的push_back
c.push_back(Sales_data("970", 25, 15.99));

在调用emplace_back时,会在容器管理的内存空间中直接创建对象,而调用push_back则会创建一个局部临时对象,并压入容器中。

在顺序容器汇总访问元素

  • 容器中没有元素,访问操作是未定义的。
  • 包括array在内每个顺序容器都有一个front成员函数,除去forward_list之外的所有顺序容器都有back成员函数。
  vector<int> c={1,2,3,4,5,6};
  if (!c.empty()){
    // val和val2是c中第一个元素值的拷贝
    auto val = *c.begin(), val2 = c.front();
    // val3和val4是c中最后一个元素值的拷贝
    auto last =c.end();
    auto val3 =*(--last); // 不能递减forward_list迭代器
    auto val4 = c.back();
    cout << val << " " << endl;
    cout << val2 << " " << endl;
    cout << val3 << " " << endl;
    cout << val4 << " " << endl;
  }
  • 访问成员函数返回的是引用:frontbackat、下标都是返回引用,如果容器是一个const对象,返回值是const的引用。
  vector<int> c={1,2,3,4,5,6};
  if (!c.empty()){
    c.front() = 42;
    auto &v = c.back(); // v是c.back()的一个引用
    v = 1024;
    cout << c.back() << endl;
    auto v2 = c.back(); // v2不是一个引用,它是c.back()的一个拷贝
    v2 = 0;
    cout <<c.back();
  }


1024
1024
  • 下标操作和安全的随机访问:at在下标越界的情况下,会抛出一个out_of_range的异常。
vector<string> svec;
cout << svec[0]; // 运行时错误
cout << svec.at(0); //抛出一个异常

顺序容器的删除操作

  • 注意:删除deque中除首尾位置之外的任何元素都会是所有迭代器、引用、指针失效。指向vectorstring中删除点之后的迭代器、引用、指针失效。
c.pop_back() 删除c中的尾元素。c为空,函数行为未定义。函数返回void
c.pop_front() 删除c中的首元素。c为空,函数行为未定义。函数返回void
c.erase(p) 删除迭代器p指定的元素,返回一个指向被删除元素之后元素的迭代器,若p是尾后迭代器,则函数行为未定义
c.erase(b, e) 将迭代器b、e指定的范围内的元素删除。若e是尾后迭代器,则函数返回尾后迭代器
c.clear() 删除所有元素,返回void

改变容器的大小

resize增大或缩小容器,array不支持。如果当前大小大于所要求的大小,容器后部的元素被删除;如果当前大小小于新大小,新元素会添加:

list<int> ilist(10, 42); // 10个int:每个值为42
ilist.resize(15); // 将5个值为0的元素添加到ilist尾部
ilist.resize(25, -1); //  将10个值为-1的元素添加到ilist末尾
ilist.resize(5); // 从ilist末尾删除20个元素

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 219,366评论 6 508
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,521评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 165,689评论 0 356
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,925评论 1 295
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,942评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,727评论 1 305
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,447评论 3 420
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,349评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,820评论 1 317
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,990评论 3 337
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,127评论 1 351
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,812评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,471评论 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,017评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,142评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,388评论 3 373
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,066评论 2 355

推荐阅读更多精彩内容

  • #1.顺序容器概述 #2.容器库概览迭代器容器类型成员begin和end成员容器定义和初始化赋值和swap容器大小...
    MrDecoder阅读 1,224评论 0 1
  • 参考书籍:C++ primer 第四版 顺序容器:它将单一类型元素聚集起来成为容器,然后根据位置来存储和访问这些元...
    Mr希灵阅读 1,088评论 0 7
  • 专业考题类型管理运行工作负责人一般作业考题内容选项A选项B选项C选项D选项E选项F正确答案 变电单选GYSZ本规程...
    小白兔去钓鱼阅读 9,000评论 0 13
  • 什么是容器 首先,我们必须理解一下什么是容器,在C++ 中容器被定义为:在数据存储上,有一种对象类型,它可以持有其...
    Jack_Cui阅读 477评论 0 2
  • C++ 标准模板库(STL) 作者:AceTan,转载请标明出处! 0x00 何为STL## STL(Standa...
    AceTan阅读 4,956评论 3 44