smart_stl:list小结

来源:互联网 发布:手机淘宝店铺装修尺寸 编辑:程序博客网 时间:2024/05/29 12:11

smart_stl小结

标签: smart_stl

这篇博客主要是分析一下我写smart_stl的心得,有小伙伴想看我的源代码请移步:
smart_stl源码

电梯直达:(csdn的Markdown不支持这个[TOC],我只能把各个总结点标记出来了)

首先我并没有完全去按照《stl源码剖析》去写,我只是领会了其中的许多好的思想。

总结1 smart_stl::list::back()代码

首先我们看一下《stl源码剖析》中back的写法:

reference back() {return *(--end());}

在这里back的代码看起来虽然很简洁 ,而且思路很清晰,但是这里面多出了两次函数调用,首先在进行end()的时候,我们就调用了一次函数,返回链表的末端节点。起始这个节点就是list类中专门的迭代器nodeIter(这个迭代器是我自己命名的,就是空链表时候的那个空节点的迭代器)。而且调用end函数的时候,还要进行一次pass by value,有造成了一个迭代器的副本;
随后,返回的迭代器又要调用operator – ()函数,又产生一些程序栈的开销(这里的知识点可以参考《深入理解计算机操作系统》),这样一个简单的reference back()产生这么多的开销实在令我感觉有点浪费了,于是我把它改变成这个样子:

template<class T, class Alloc>typename list<T, Alloc>::reference list<T, Alloc>::back(){    return nodeIter.nodePtr->prev->data;}

这里的nodeIter就是链表中指向空节点的迭代器,它里面含有指向空节点的指针,所以nodeIter.nodePtr就是这个空节点;list中的列表是一个双向链表,那么该空节点前的一个节点就是链表中“最后一个节点”,这个节点就是nodeIter.nodePtr->prev,由于它是一个指针,那么这个节点指针访问数据就要采用“->”操作符,所以这个链表中最后一个节点的数据就是:nodeIter.nodePtr->prev->data,这个语句的逻辑也是比较清晰的,重要的是它没有产生函数调用的开销。

总结2 后置++需要注意的地方

接下来,我们看一下大家都比较数据的操作符重载,大家对操作符重载可能都比较熟悉:oprator++()是前置的++操作,operator++(int)是后置的++操作;但是在写后置++重载的时候,需要注意一点就是它的返回值应该是const iterator!!!
那么,为什么必须要将返回值置为const类型呢?
看过《C陷阱与缺陷》的同学肯定做过第一章最后的一道题,大致是什么我忘记了,但是精髓我还是记得很清晰的,我就来模仿一下:
如果int a = 1;int b = 1;那么a+++++b;是多少?
这个问题就是告诉我们a++后不能连续进行++操作,这在C语言中时不被允许的。所以我们迭代器的后置++操作也应该是不被允许进行连续的后置++操作。所以我们要将list中的迭代器的后置++的返回值也设置成const类型。

—————————2015/6/18新增分割线———————————

总结3 smart_stl::list::front()分析

对于list中的front和back,源码中时这样写的;

reference front() {return *begin();}

虽然源码中将这个函数写成了inline函数,但是在函数内部还是涉及到函数的调用,函数调用中还是在程序栈中增加了一个“返回地址”的内容;我认为其实可以将这个函数更改成这个样子:

template<class T, class Alloc>typename list<T, Alloc>::const_reference list<T, Alloc>::front() const{    return nodeIter.nodePtr->next->data;}

这样我们是直接引用的指针,所以这样思路也是比价清晰的,而且没有产生函数调用(个人认为是这样的,有问题的可以在下面和我讨论啊^-^)。

—————————2015/6/24端午分割线———————————
估计这篇文章会有很多的分割线,既然是总结就要认真一点,哈哈。

总结4 copy()和uninitialized_copy()究竟用哪个?

其实在写vector的时候,我就搞不懂,uninitialized_copy这货和copy有什么不同,譬如我在写vector的赋值构造函数的时候,里面就用到了uninitialized_copy,但是这个时候我还是分不太清楚这个函数和copy有什么不同,后来我竟然把这个事情给忘记了(有什么思想还是马上记录下来的好~~~像我这样)
今天看到一篇csdn的问题:请问uninitialized_copy跟copy有什么不同啊?
我又再一次看到这个问题,赶紧查一查,就查到了cplusplus的reference,这里贴个链接uninitialized_copy

里面有这样的一句话:Unlike algorithm copy, uninitialized_copy constructs the objects in-place, instead of just copying them. This allows to obtain fully constructed copies of the elements into a range of uninitialized memory, such as a memory block obtained by a call to get_temporary_buffer or malloc.

我们可以看到在这句话中,reference已经说的很清楚了,并不能用copy来替代它,uninitialized_copy更注重的是construct the objects in-place,只是它在construct对象的时候是依据了result上的值。uninitialized_copy是用在uninitialized memory。那么这片内存区中还没有对象,还需要构造!!!而copy函数中经常用到的语句*first = *result;是因为此时已经构造出了对象。所以我们就分辨出了uninitialized_copy和copy的应用场景:
对于uninitialized memory就使用uninitialized_copy

0 0