第十六章

C++类库(不是内裤)和stl博大精深,我等初学者肯定现在只有远观还不能亵玩了。本节讲到stl后面基本就基本只能算看懂了,估计要真明白会用得专门那本书去学。这章写到第五节就基本写不下去了。。。先贴上来留个纪念吧,等以后明白了再回来修改

现在编程很少有人重头编写了,基本都是直接运用然后部分重写前辈编写的代码。C++的类库就是为这个设计的。这一章首先从最常见的string类讲起。

1.string类

大家现在对string类也该很熟悉了,就是一个处理字符串的类。虽然目的很简单,但为了应付各种运用,包含的内容也非常多。光是构造函数就有7个,之后C++11又添了两个。书里面表16.1和程序清单16.1列出了所有构造函数的用法. 其实这几种方法无外乎就是怎么把其他已经存在的string或者char数组,string的一部分,char数组的一部分来用来初始化新建的string。既然string类实质上也是一个char数组,那么也可以通过[#]来直接调用string的第#个字符。String类也支持+或者赋值=操作,也支持cout输出或者cin输入。

对于string类,有两种方式可以输入

string str;

cin >> str; //只能读一个单词

getline(cin. Str); //读一行,不包括\n

string类和char数组最大的区别就是string类少了很多对字符串长度的限制,代价就是string类必须包括很多应付这个问题的函数。

但是string类对对象还是有最大允许长度限制的,由常量string:: npos来指定,默认为unsigned int的最大值。

String类也支持比较字符串,包括比较string类字符串和比较char数组字符串,运用起来很简单: <, =, >就行。这个基本就是比较每个字符的顺序。更有意义一点点是确定字数串长度的方法:size(), length()。 这两个方法作用一样,支持size()兼容STL。

String类还有提高查找字符的方法find(), 可以返回被查找字符第一次出现的位置。书中给了一个猜单词的游戏的例子来说明这个函数。

此外,string类还可以删除字符串的部分或全部内容,用一个字符串的部分或全部内容替换另一个字符串的部分或全部内容,插入或删除数据,等等等等。具体看附录F

 

2. 智能指针

智能指针是指行为类似指针的类对象,加以其他功能。什么时候需要它了,看书中的例子

Void remodel(string & str)

{

       String * ps = newstring(str);

       …..

       Str = ps;

       Return;

}

很明显,这里ps没有delete,但是不是加了delete就没问题了呢。 如果…..里面有个exception throw的函数,那么遇到exception就跳到throw那去了,delete不会执行。用户也说了,大不了我在try catch里面也加上delete呗。可是可以,不过这就太麻烦了,而且很多人都会忘记。

但是如果ps是一个类,它自己有一个析构函数,会delete掉指针,那么就没问题了。怎么把ps弄成一个类呢, 有三个智能指针模板(auto_ptr, unique_ptr, shared_ptr)都可以定义类似指针的对象,可以将new获得的地址赋给这种对象,当智能指针过期是,其析构函数将使用delete来释放这些内存。

要创建智能指针对象,必须包含头文件memory,然后声明。比如如果是double类的指针:

auto_ptr<double> pd(new double);

unique_ptr<double> pdu(new double);

shared_ptr<double> pds(new double);

用了智能指针就不要再用delete了。声明之后用法基本跟常规指针用法相同。

Auto_ptr实际上C++11不再支持, 还有这三种指针的区别是什么了,看下面。

auto_ptr<string> ps1 (new string(“string”));

auto_ptr<string> ps2;

ps2 = ps1;

这时候ps1, ps2都指向同一个string对象,这是不支持的。解决办法可以是建立所有权概念,对于特定的对象,只能有一个智能指针可以拥有它和delete它。这就是auto_ptr和unique_ptr的策略。另外一种方案就是创建智能更高的指针,跟踪引用特定对象的智能指针数,这样成为引用计数。例如赋值时计数加1,指针过期是计数减1.仅当最后一个指针过期是,才调用delete,这是shared_ptr所采用的策略。

应该如何选择智能指针呢,如果程序要使用多个指向同一个对象的指针,应选择shared_ptr,这样的情况包括:有一个指针数组,并使用一些辅助指针来表示特定的元素,比如最大或最小;两个对象包含都指向第三个对象的指针;STL容器包含指针。如果程序不需要多个执行同一个对象的指针,则可以使用unique_ptr

 

3. 标准模板库STL

标准模板库就是听说过很多次的STL了,standard templatelibrary, 其提供了一组表示容器,迭代器,函数对象和算法的模板:

容器:一个与数组类似的担忧,可以储存若干个值,stl要求储存的值必须是一个类型

算法:完成特定任务的方法

迭代器:用来遍历容器的对象

函数对象是类似于函数的对象,可以是类对象或者函数指针。

总的来说STL能够构造各种容器(包括数组,队列和链表),然后执行各种操作,包括搜索排序等

STL一个很简单的例子就是我们学过的vector类,用法很简单:

vector<int>ratings(5); 这样就创建了一个包含5个int数据的vector对象了,之后对象的用法跟普通数组类似。

如果到这里就结束了那创建这个vector类完全可以用普通数组代替。vector必然还有其他功能了。vector包含了STL容器都提供的一些基本方法,包括size() – 返回容器中元素数目,swarp()-交换两个容器的内容,等等。

迭代器怎么用了,首先它可以是指针,也可以是一个可以执行类似指针操作-如解除引用或者递增。先看怎么声明:

vector<int>::iteratorpd; 这样就声明了一个给容器vector的int类型对象的迭代器。之后我们就可以

pd =ratings.begin(); //将pd指向ratings的第一个元素

*pd = 22.3;//给pd指向的对象赋值

++pd; //将pd指向下一个元素

可以看出来迭代器和指针有很大的相似。

此外书中还介绍了在队列末尾插入新值得push_back()操作,删除摸个区间元素的erase()方法,或者添加元素的方法。

STL还从更广泛角度定义了很多非成员函数来执行诸如搜索,排序,随机排序等操作,有点这些函数与STL类的成员函数重名,要注意区分。

书中举了三个这样的函数for_each(), random_shuffle(), sort(). 我觉得现在也肯定记不住他们的用法,但一定得知他们的存在。有意思的怎么用sort来对对象或者结构排序,方法就是要重载运算符<来决定怎么来比较对象或者结构的大小

 

4 泛型编程

泛型编程和面向对象编程不同,泛型编程关注的是算法,目的是编写独立于数据类型的代码。C++中的模板就是泛型编程的基础。

首先再来看看迭代器,书里面说迭代器是理解STL的关键说在,因为它可以使算法独立于使用的容器类型。为什么这么说呢。书里面举了一个查找元素并返回的find()函数的例子。这个函数要求不仅能独立于容器中存储的数据类型,而且独立于容器本身的数据结构。模板可以满足前者,而迭代器可以作为遍历容器中的值得通用表示。这是因为迭代器可以:

可以执行解除引用的操作,以便能够范围它引用的值

能够将一个迭代器赋给另一个

能够使用迭代器遍历容器中的所以元素

那么我们现在可以首先对每个容器类定义相应的迭代器类型,可以实现*和++之类的。使用容器类是,就不需要迭代器怎么实现的,只需知道有这么一个东西,begin()返回第一个元素,end()返回最后一个元素,等等。

不同算法对迭代器的要求不同,例如有的算法只需要读取数据,有的则需要修改。STL定义了五种迭代器:输入迭代器,输出迭代器,正向迭代器,双向迭代器和随机范围迭代器。所以迭代器都可以执行解除引用操作,也可以进行比较。下面看迭代器的不同

输入迭代器:

可以通过解除引用来读取容器的值,但不能修改。输入迭代器是单通行迭代器,可以递增,但不能倒退

输出迭代器:

只能通过解除引用来修改容器的值,但不能读取。也是单通行。

正向迭代器:

只使用++来遍历容器,但总是按相同的顺序遍历一系列值。即可以能够读取和修改数据,也可以只能读取数据。

双向迭代器:

具有正向迭代器的所有特性,同时支持递减运算符

随机访问迭代器:

顾名思义,就是可以访问容器任意位置的元素。

那么问题来了,要这么多迭代器干嘛,有一个随机访问迭代器不就行了么。答案是为了在编写算法尽可能使用要求最低的迭代器,并让他适用于容器的最大区间。其实说白了就是一个效率问题了。

STL提供了一下预定义迭代器,使用时需包含头文件iterator

说实话看到这里基本看不懂了,平时基本没有接触这些方面的应用,所以看起来很吃力。先了解吧,到以后遇到实力的时候再回过头来看。

既然迭代器都有不同种类,那么容器也应该有了,C++过去有11个种类dequei,list,queue, priprity_queue, stack, vector, map, multimap, set, multiset 和bitset,后来C++11有增添了几种。。。。现在我只能在这里说,每个容器都有自己存在的原因。。。

 

5. 函数对象

函数对象又叫函数符functor,是可以以函数方式与()结合使用的任意对象,包括函数名,指向函数的制作和重载了()运算符的类对象。

该节剩下的就开始介绍了很多函数符概念,非常拗口,也不好理解,我短时间也想不出来照抄之外的解释了。。所以这里就不抄书了。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值