点击查看Evernote原文

#@author:       gr
#@date: 2014-10-01
#@email: forgerui@gmail.com

Part 2: STL顺序容器(第9章)

一、标准库array(C++11)

array的大小固定,不能省去,它是容器的一部分。

//保存42个int, 初始1,2,其余40个元素初始为0
array<int, 42> = {1, 2}
//保存24个string
array<string, 24>
array<int, 10>::size_type i; //正确
array<int>::size_type j; //错误,没有大小
//类的话必须有一个默认构造函数
array<Widget, 10> aw;

内置数组不能进行数组赋值,拷贝,array可以。

int digs[10] = {1, 2, 3};
int cpy[10] = digs; //错误,不支持赋值
array<int, 10> dig = {1, 2, 3};
array<int, 10> cp = dig; //正确,可以进行赋值,数组大小要一致

二、容器的关系运算符

只有当元素定义了相应的比较运算符,才可以使用容器的关系运算符。

vector<int> v1 = {1, 3, 7};             //初始列,C++11
vector<int> v2 = {1, 3, 7, 9};
v1 < v2 //true,所有元素相等,v1数目更少

三、STL容器使用的是拷贝

用一个对象初始化容器,是将该对象的拷贝放进容器中的,容器中的元素修改与原来的对象没有任何影响。

四、使用emplace_back,emplace,emplace_front

emplace可以直接在内存中创建对象,并且效率更高。

vector<Sales_data> c;
//直接在空间创建对象,节省开销
c.emplace_back("123", 25, 25.99);
//编译错误,没有3个参数的构造
c.push_back("123", 25, 25.99);
//构造临时对象,拷贝进入容器,销毁对象
c.push_back(Sales_data("123", 25, 25.99));

五、容器的访问成员函数

可以使用front,back进行直接访问,也可以通过迭代器进行解引用,获取元素,但在进行访问之前,最好要检测容器是否为空,如果为空,将会产生不确定行为。

对提供了随机访问的容器可以使用下标访问(如v[0]),list则不存在下标访问。下标访问返回的是元素的引用,对其赋值可以直接修改容器中元素的值。下标运算不检查是否在合法范围内,下标越界是一种严重的错误,会导致runtime error。也可以使用at成员函数,如果下标越界,at会抛出一个out_of_range异常。

vector<string> sv;      //空vector
cout << sv[0]; //运行时错误
cout << sv.at(0); //抛出一个out_of_range

六、容器的删除操作

forward_list没有pop_back函数,vectorstring没有pop_front操作。erase(p);删除迭代器p所指定的元素,erase(p, q);删除迭代器p到q范围的元素。在删除之前,必须保证元素是存在的。

forward_list的删除需要两个迭代器,一个是正在处理元素的,一个是前驱元素的迭代器。

//删除容器中的奇数
forward_list<int> flst = {0, 1, 2, 3, 4, 5, 6, 7};
auto prev = flst.before_begin(); //表示flst的“首前元素”
auto curr = flst.begin();
while (curr != flst.end()) {
if (*curr % 2){ //元素为奇数
curr = flst.erase_after(prev); //删除它并移动curr
}else{
prev = curr;
curr++;
}
}

七、改变容器的大小

使用resize来改变容器的大小,array不支持resize。如果当前大小大于所要求的大小,容器后部的元素会被删除;如果当前大小小于要求的大小,将新元素加入到容器中。

list<int> il(10, 42);
il.resize(15); //在最后加入5个0
il.resize(25, -1); //在最后加入10个-1
il.resize(5); //删除末尾的20个元素

八、在循环中保持迭代器

容器的操作可能会使已有的迭代器失效,如何在循环过程中保持这些迭代器,以使整个循环过程正确?

办法是使用成员函数操作的返回值更新迭代器,虽然list的某些操作并不影响迭代器,但为了统一,最好所有的顺序容器都使用相同的形式。

vector<int> vi = {1, 2, 3, 4, 5};
auto iter = vi.begin();
iter = vi.insert(iter, 2); //用insert返回值更新迭代器
iter = vi.erase(iter); //删除元素

九、不要试图保存end返回的迭代器

容器的操作会改变end()返回的迭代器,所以不要保存它。这也是为什么在循环中,为何反复调用v.end()进行判断是否结束。

it = v.begin();
while (it != v.end()){ //反复调用v.end()检查
//...
}

十、理解vector是如何增长的

capacity表示容量,是已经申请的内存空间,size是已经保存的元素的数目。

使用reserve改变容器的容量,resize改变容器的大小。

vector内存不够用的时候,会把整个vector复制到更大的内存空间中,造成开销变大。

使用reserve事先申请大的空间,可以避免vector的拷贝,但如果容量过大,则会浪费。

《Effective STL》中的Topic17里面讲解使用"swap技巧"去除多余的容量,实际上,C++11中提供了shrink_to_fit函数来退回不需要的内存空间。

十一、string独有的一些操作

使用string进行字符串处理,可以极大地简化我们的工作。

  1. 一般程序设计语言,都会提供substr函数进行字符串截取。

     //pos开始位置,n截取的个数
    s.substr(pos, n);
  2. insert, erase基于下标版本

    string提供了基于下标版本的成员函数。

     s.insert(s.size(), 5, '!');     //在最后插入5个!
    s.erase(s.size()-5, 5); //删除最后5个元素
  3. append,replace

     string s("C++ Primer"), s2 = s;
    s.insert(s.size(), " 4th Ed."); //追加
    s.append(" 4th Ed."); //等价上面insert方法

    replaceeraseinsert操作的简写:

    s.erase(11, 3);

    s.insert(11, "5th");

    s2.replace(11, 3, "5th"); //等价于上面两句

    s2.replace(11, 3, "Fifth"); //删除3个字符,添加5个也是可以的

  4. 搜索操作

    string一共有6种搜索操作,分别是find, rfind, find_first_of, find_first_not_of, find_last, find_last_not_of。这些都是大小写敏感,返回第一个匹配出现的位置。

     string name("AnnaBelle");
    name.find("Anna"); //返回0
    //使用find_first_of查找在list_c字符出现的第一个位置
    string list_c("cnl");
    name.find_first_of(list_c); //返回1,即n第一次出现的地方
  5. 数值转换

     int i = 42;
    string s = to_string(i); //将i转换为字符表示形式
    double d = stod(s); //将string转换为浮点数

十二、容器适配器

适配器是一种机器,接受一种已有的容器类型,对其改造,使其行为看起来像一种不同的类型。我们定义了适配器,就只能使用适配器提供的操作,不能使用底层容器的操作。

stack栈适配器可以使用vector,deque,list实现;queue可以使用deque,list实现,因为vector没有pop_front

###学习《C++ Primer》- 2的更多相关文章

  1. 学习C++ Primer 的个人理解(一)

    <C++ Primer>这本书可以说是公认的学习C++最好的书,但我觉得不是特别适合作为教材,书中内容的顺序让人有些蛋疼.我个人认为初学此书是不能跳着看的.如果急于上手的话,我更推荐< ...

  2. 学习C++ Primer 的个人理解(九)

    这一章介绍顺序容器,在之前的第三章中,了解到的vector就属于顺序容器的一种. 一个容器就是一些特定类型对象的集合. 除了vector,还有哪些顺序容器? vector: 大小可变,随机访问的速度很 ...

  3. 学习C++ Primer 的个人理解(三)

    第三章,主要内容是字符串和数组.感觉作者的意图是希望读者可以早一点可以写出简单的小程序,并且可以早点接触迭代器这种思想. 在我看来,这种内容的难度并不大. 对于编程来说,最重要的应该是思想,类似vec ...

  4. 学习C++ Primer 的个人理解(二)

    本身就一定基础的读者我想变量常量这些概念应该已经不是问题了.但是本章还是有几个重点,需要特别留意一下的: 1.初始化和赋值是不同的操作 2.任何非0值都是true 3.使用新标准列表初始化,在有丢失精 ...

  5. 学习C++.Primer.Plus 11 使用类

    1.操作符重载 重载操作符的几个限制: a)         重载的至少有一个操作数是用户定义的类型,这将防止用户为标准类型重载操作符. b)         不能违反操作符原有来的句法规则. c)  ...

  6. 学习C++.Primer.Plus 10 对象和类

    1.类的声明和定义 类的声明和定义. 类声明的格式如下: class className { private://private 是类对象的默认访问控制,因此,可以省略 data member del ...

  7. 学习C++.Primer.Plus 8 函数探幽

    1. 内联函数 普通函数调用: 存储调用指令的地址->将函数参数复制到堆栈->跳到函数地址执行代码(返回值放到寄存器)->跳回调用指令处 2.  当代码执行时间很短,且会被大量调用的 ...

  8. 学习C++.Primer.Plus 7 函数

    C++的返回值类型不能是数组 函数原型中的变量名相当于点位符,因此不要求提供变量名. void cheers(int); C++中不指定参数列表时就使用活力号: void saybye(...); 通 ...

  9. 学习C++.Primer.Plus 6 分支语句和逻辑操作符

    ||. &&操作符是一个顺序点 < 操作符从左向右结合 ; < age < )//17<age为true, = 1,肯定 < 27.所以为整个条件为tru ...

  10. 学习C++.Primer.Plus 5 循环和关系表达式

    C++将赋值表达式的值定义为左侧成员的值 赋值操作符是自右向左结合的 cout.setf(ios:: boolalpha);//调用设置标记,命令cout输出true或false,而非1或0. 任何表 ...

随机推荐

  1. 函数 stat() 详解

    先看看MSDN的解釋: stat(): Get status information on a file. Parameters:     path:  pointer to a string con ...

  2. MSSQLSERVER数据库- 数据类型Timestamp

    Timestamp:亦称时间戳数据类型,它提供数据库范围内的惟一值,反应数据库中数据修改的相对顺序,相当于一个单调上升的计数器.当它所定义的列在更新或者插入数据行时,此列的值会被自动更新,一个计数值将 ...

  3. JavaScript要点 (六) 函数参数

    JavaScript 函数对参数的值没有进行任何的检查. 函数显式参数(Parameters)与隐式参数(Arguments) 函数的显式参数: functionName(parameter1, pa ...

  4. Windows 7 EXE图标丢失修复方法

    有过Win7下的一些EXE文件图标莫名奇妙丢失,但功能却正常的情况吗?这是图标缓存的问题,应该是Win7的bug. 在命令提示符下输入下列命令即可恢复. 以下是代码片段: taskkill /im e ...

  5. 用CSS让网页背景图片居中的方法

    网页背景居中的方法有很多种的.这里介绍一些用CSS让背景图片居中的方法. 让背景图片居中的第一个方法是用像素设定,很多都用这种,但是也是最麻烦的: <div style="width: ...

  6. 飘逸的python - 理解打开文件的模式

    当我们用open()函数去打开文件的时候,有好几种打开的模式.   'r'->只读 'w'->只写,文件已存在则清空,不存在则创建. 'a'->追加,写到文件末尾 'b'->二 ...

  7. vmware安装 ios10.8 过程

    前言:由于mac笔记本太贵,并且对于用thinkpad 习惯的我,实在是不想买mac,没办法,只能在win7下面使用vmware 安装mac虚拟机了.但是ios的版本一直变,vmware也一直在升级, ...

  8. QSqlQueryModel的实例操作

    QSqlQueryModel类为SQL的结果集提供了一个只读的数据模型,下面我们先利用这个类进行一个最简单的操作. 我们新建Qt4 Gui Application工程,我这里工程名为queryMode ...

  9. PHP之open_ssl

    http://www.wapm.cn/phpdoc/zh/openssl.installation.html http://liuxufei.com/weblog/jishu/376.html dem ...

  10. Apache的rewrite规则详细介绍

    Apache的rewrite规则详细介绍 发布日期:2008-09-02 16:16 来源: 作者: 点击:7044 rewrite标志 R[=code](force redirect) 强制外部重定 ...