阅读笔记《C++标准程序库》

来源:互联网 发布:淘宝众筹是什么意思 编辑:程序博客网 时间:2024/05/01 06:29

 《C++标准程序库》

         ——————2013/1

 

第五章 

5.1 STL Components   STL的基本观念是将数据和操作分离(与OOP观念相矛盾),数据由容器container管理,操作由算法algorithm定义,迭代器iterator充当粘合剂。

 

5.2 Containers   序列容器Sequence containers(可序ordered):vectordequelist

     关联容器Associative containers(已序sorted):setmultisetmapmultimap

   容器适配器Container adaptersstackqueuepriority_queue

 

5.3 Iterator   任何容器都定义了两种迭代器型别:

Container::iterator /写     Container::const_iterator 只读

双向迭代器(递增++、递减--):listsetmultisetmapmultimap

随即存取迭代器(++--+-):vectordequestring

 

5.4 Algorithm   区间采用半开半闭,当begin() == end()容器为空

 

5.5 Iterator Adapter   三种迭代器适配器:

1.  Insert iteratorback_inserter(container)/front_inserter(container)/inserter(container,pos)运用copy函数,目标容器空间不足可用:copy(coll1.begin(), coll1.end(), front_inserter(coll2));只要容器coll2提供有push_front()则能正常运行。

    2.  Stream iteratoristream_iteratorostream_iterator

从标准输入读入容器:

copy(istream_iterator<int>(cin), istream_iterator<int>(), back_inserter(coll1));

从容器输出到标准输出:

copy(coll1.begin(), coll1.end(), ostream_iterator<int>(cout,  ”  ”));

3.  Reverse iteratorrbegin(), rend()

 

5.6 Manipulating/Modifying Algorithm   

       (为使算法达成最大弹性,容器和数组均适用)任何“以迭代器访问容器元素”的算法,都不得(无法)透过迭代器调用容器类别所提供的任何成员函数(数组本身没有成员函数),即不必了解容器细节。  例:remove()算法删除一个容器的末尾元素,会返回一个新的指向结尾的迭代器,但是容器本身的end()却未改变,需要程序员去完成。

为此,(成员函数vs算法),应永远优先选择成员函数。

 

5.7 User-Defined Generic Functions

 

5.8 以函数作为算法的参数

1. void Print(int value);

   for_each(col1.begin(), col2.end(), Print());

   作用:该容器内,每个元素均调用一次Print().

2. 一元判断式:指定函数仅一个参数,返回bool类型

3. 二元判断式:指定函数有两个参数,返回bool类型

 

5.9 Function Object

一个类class Fun,让它重载operator(), 那么该类对象就有了函数特性,即为函数对象。

 

5.10 容器内的函数

1. 容器元素应满足的条件。

2. STL只支持value语义,不支持reference,这样利弊参半。只能用指针代替,但是存在一般指针的常见问题,例如比较时,比较的事指针的值,而不是指针所指的值。

 

5.11 STL内部的错误处理和异常处理

1. 为提高效率,STL的错误检查几乎没有。所以违反规则就会导致未定义行为。

迭代器,区间,覆盖等操作很易出错。

2. C++异常处理的一些基本保证:P139140

 

第六章 STL Container

6.1 容器的共通能力和共通操作

1. 容器的元素都是value,而非reference;元素形成一个序列,即可以一次或多次遍历每个元素;传参时必须符合要求,否则引起未定义行为。

2. 容器类别的共通操作函数:P145

3. vector<int> c(istream_iterator<int>(cin), istream_iterator<int>()); 可能被当做一个函数。所以要写成 vector<int> c( ( ), ( ) );

4. 成员函数 empty() 等价于 size()==0;但前者效率更佳。

5. 赋值操作是将源容器的所有元素拷贝到目标容器,原目标容器的所有元素被删除,所以代价高昂。若源容器不再使用可采用swap()交换,它只交换内部指针,所以时间复杂度为常数。

 

6.2 Vector namespace std{

template <class T,  class Allocator=allocator<T> >

class vector;}

1. size()当前元素个数, max_size()最大可分配的容量, capacity()动态数组当前容量, reserve()预留容量(为提高效率)

2. vector的操作函数P150151152154

3. vector<bool>特例。 动态位存储,节省空间

 

6.3 Deque namespace std{

template <class T,  class Allocator=allocator<T> >  

class deque; }

1. 采用动态数组,但是和vector不一样的是 deque采用多个区块,所以内存重分配时优于vector,因为无需复制所有元素。

2. 由于第一点,所以元素的存取和迭代器的动作稍慢,需要在不同的区块间跳转,需要特殊的智能指针。

3. deque不提供容量操作capacityreserve;但是多了在头插入删除push_frontpop_front,其它的基本和vector一样。

 

6.4 List namespace std{

template <class T,  class Allocator=allocator<T> >

class list;}

1. list采用双向链表,不提供随机存取,只有back()front()能直接存取,所以不提供下标操作[]at();但在任何位置安插删除元素都非常快。

2. 提供多种成员函数P169-171

3. STLlist对异常安全性提供了最佳支持。

 

6.5 Set 和 Multiset

namespace std{

  template <class T, class Compare=less<T>, class Allocator=allocator<T> >

  class set/multiset;}

1. 排序准则默认为函数对象less<T>,可用两种方法传入排序准则:

(1)template参数定义:std::set<int, std::greater<int> > col1;

(2)以构造函数定义:set<Elem, Op>   详见P177.

2. 元素必须的排序准则:反对称(x<y,y<x);可传递;非自反(x<x永为假)

3. 只有元素类型,比较准则都相同容器才能比较,否则发生编译错误。

4. 数据结构采用:红黑树(是二叉平衡树的一种,二叉平衡树是二叉排序树的一种)

5. 因为插入元素时就自动排序,所以容器内的元素不能改变其值,而双向迭代器指向的元素都被视为常数;若要改变元素值,只能删除旧的,插入新的。

6. 多次插入删除时,一次处理完比逐一调用快得多。插入函数有一个位置参数作为插入提示,可大大加快速度。

 

6.6 Map 和 Multimap

namespace std{

Template< class Key,  class T,  class Compare = less<key>, 

 class Allocator = allocator<pair<const Key, T> > >

class map/multimap;}

1. map拥有set的所有能力和操作函数。set是特殊的mapkeyvalue相等。

2. map提供下标操作符,可直接存取元素,multimap没有。若指定下标key不存在,则自动创建,而value采用该类型的默认构造函数。

3. 所有元素的key被视为常数。若要修改key,而不改变value,可采用一个比较方便的方法:map1[“new_key”]=map1[“old_key”]; map1.erase(“old_key”);

4. 实例:关联式数组p207、字典p209

5. 综合实例:如何撰写使用function object;如何在执行期定义排序准则;如何在“不在乎大小写”的情况下比较字符串(toupper();) P213

 

6.7 其他STL容器

1. STL是一个框架。使用其它数据结构定义容器的三种不同方法:P217

(1)侵入式:直接提供STL所需接口,如begin(),end()之类的常用函数。这种方法是以某种特定方式编写容器,所以叫侵入式。  

(2)非侵入式:只提供特殊的迭代器作为算法与特殊容器的界面,只需遍历容器所有元素的能力。

(3)包装法:上述两种方法的组合,将一个数据结构包装出于STL容器相似的接口。

2. 将数组包装成array容器的实例。 P219

 

6.8 动手实现reference语义

使用引用计数的智能指针作为容器的元素。

 

6.9 各容器的运行时机

P226

 

6.10 细说容器内的型别和成员

1. 容器内的型别:reference, const_reference, iterator, const_iterator, reverse_iterator, const_reserve_iterator, size_type, difference_type, value_type, key_type, mapped_type, key_compare, value_compare, allocator_type.

2.  Constructor, Copy, Destructor :  P231

3. Nomodifying Operations :  P233

4. Assignments:  operator=, assign(), swap().

5. 返回元素:front(), back(), at(), operator[].

   返回迭代器:begin(), end(), rbegin(), rend().

6. Inserting 、 Removing : P240

7. Lists的特殊成员函数:unique(), splice(), merge(), sort(), reverse().

8. STL容器的异常处理: P249

 

第七章 STL Iterator

7.1 迭代器头文件: <iterator>容器本身已包含该头文件。

 

7.2 迭代器类型: InputOutputForwardBidirectionalRandom access

 

7.3 迭代器相关辅助函数:

       //使迭代器前进n步,n可以为负数

1. #include<iterator> void  advance(InputIterator&  pos, Dist  n);

   //返回两迭代器之间的距离

2. #include<iterator> Dist  distance(InputIterator  pos1,  InputIterator  pos2);

       //交换两个迭代器所指元素的内容

3. #include<algorithm> void  iter_swap(ForwardIterator pos1, ForwardIterator pos2);

 

7.4 迭代器适配器

1. 逆向迭代器:逆向迭代器指向的是实际元素位置,返回的是所指位置的下一跳的值。

例:begin()rend()所指位置相同,但是rend()取值返回的是begin()所指位置的前一个;end()rbegin()所指位置相同,但是rbegin()取值返回的是end()所指的起一个元素。

逆向迭代器直接用一般迭代器初始化:pos=v.begin(); vector<int>::reverse_iterator rpos(pos);

逆向迭代器转化为正向迭代器使用成员函数:pos = rpos.base();

2. 安插型迭代器:

名称

Class

其所调用的函数

生成函数

Back inserter

back_insert_iterator

push_back(value)

back_inserter(coll)

Front inserter

Front_insert_iterator

push_back(value)

front_inserter(coll)

General inserter

Insert_iterator

insert(pos, value)

inserter(coll, pos)

3. 流迭代器

Ostream迭代器:template ... class ostream_iterator;

Istream迭代器: template ... class istream_iterator;

所有istream迭代器只要任何一次读取失败都会变成end-of-stream,所以每进行一次读取都都应将istream迭代器与end-of-streamistream迭代器的default构造函数生成)比较,检查这个迭代器是否合法。

 

7.5 迭代器特性

template <class T>

struct iterator_traits {

typedef  typename  T::value_type            value_type;

typedef  typename  T::difference_type        difference_type;

typedef  typename  T::iterator_category       iterator_category; 

typedef  typename  T::pointer               pointer;

typedef  typename  T::reference             reference;

};

 

第八章 STL Function objects

8.1 函数对象(或叫仿函数functor)的概念: 定义了operator()的对象。

函数对象比一般函数更灵巧,因为它可以拥有状态,而且不止一个状态;

函数对象是class,有型别的。所以可以将它当做template参数传递;

执行速度上函数对象通常比一般函数快。

函数对象做函数参数传递时是passed by value,而不是reference!若需传递reference则要对template参数进行特化: 

generate_n<back_insert_iterator<list<int> >, int, Functor&>( back_inserter(coll),  4,  seq);

 

8.2 预定义的函数对象 P305#include<functional>

1. 函数适配器:指能将两个函数对象结合起来的函数对象(函数复合)bind1st, bind2nd, not1, nos2 

2. mem_fun_ref, men_fun(不能直接将一个成员函数传给一个算法,需要运用适配器,这两者调用的成员函数必须是const) 

3.  ptr_fun(针对非成员函数)

 

8.3 辅助用(综合型)函数对象:实现多个函数对象的组合使用,如:A and B

1. 一元组合函数适配器

2. 二元组合函数适配器

 

第九章 STL Algorithm

 

 

第十章 STL Special Containers

10.1 Stack

Namespace std {

Template <class T, class Container = deque<T> >

Class stack; }

 

核心接口:push()   top()    pop()

 

10.2 Quene

Namespace std {

Template <class T, class Container = deque<T> >

Class queue; }

 

核心接口:push()   front()     pop()    back()

 

10.3 Priority Queue

Namespace std {

Template <class T, class Container = vector<T>,

Class comjpare = less<typename Container::value_type> >

Class priority_queue; }

 

核心接口:push()     top()    pop()

 

10.4 Bitset

Bitset是容量不可变得位集,vector<bool>则是动态位集。

Namespace std {

Template <size_t  Bits>

Class bitset; }

 

 

 

 

0 0
原创粉丝点击