第二十七课 再论智能指针(上)

思考:

  使用智能指针替换单链表LinkLIst中的原生指针是否可行?

将LinkList.h中的Node指针全部改成智能指针:

  1 #ifndef LINKLIST_H
  2 #define LINKLIST_H
  3
  4 #include "List.h"
  5 #include "Exception.h"
  6 #include "SmartPointer.h"
  7
  8 namespace DTLib
  9 {
 10
 11 template < typename T >
 12 class LinkList : public List<T>
 13 {
 14 protected:
 15     struct Node : public Object
 16     {
 17         T value;
 18         SmartPointer<Node> next;
 19     };
 20
 21     mutable struct : public Object
 22     {
 23         char reserved[sizeof(T)];
 24         SmartPointer<Node> next;
 25     }m_header;
 26
 27     int m_length;
 28     int m_step;
 29     SmartPointer<Node> m_current;
 30
 31     Node* position(int i) const    //  O(n)
 32     {
 33         //Node* ret = reinterpret_cast<Node*>(&m_header);
 34         SmartPointer<Node> ret = reinterpret_cast<Node*>(&m_header);
 35
 36         for(int p = 0; p < i; p++)
 37         {
 38             ret = ret->next;
 39         }
 40
 41         return ret.get();
 42     }
 43
 44     virtual Node* create()
 45     {
 46         return new Node();
 47     }
 48
 49     virtual void destroy(Node* pn)
 50     {
 51         delete pn;
 52     }
 53
 54 public:
 55     LinkList()
 56     {
 57         m_header.next = NULL;
 58         m_length = 0;
 59         m_step = 1;
 60         m_current = NULL;
 61     }
 62
 63     bool insert(const T& e)
 64     {
 65         return insert(m_length, e);
 66     }
 67
 68     bool insert(int i, const T& e)   // O(n)
 69     {
 70         bool ret = ((0 <= i) && (i <= m_length));
 71
 72         if( ret )
 73         {
 74             Node* node = create();
 75
 76             if( node != NULL )
 77             {
 78                 Node* current = position(i);
 79
 80                 node->value = e;
 81                 node->next = current->next;
 82                 current->next = node;
 83
 84                 m_length++;
 85             }
 86             else
 87             {
 88                 THROW_EXCEPTION(NoEnoughMemoryException, "No memery to insert new element...");
 89             }
 90         }
 91
 92         return ret;
 93     }
 94
 95     bool remove(int i)   // O(n)
 96     {
 97         bool ret = ((0 <= i) && (i < m_length));
 98
 99         if( ret )
100         {
101             SmartPointer<Node> current = position(i);
102
103             SmartPointer<Node> toDel = current->next;
104
105             if( m_current == toDel )
106             {
107                 m_current = toDel->next;
108             }
109
110             current->next = toDel->next;
111
112             m_length--;
113
114             // destroy(toDel);
115
116         }
117
118         return ret;
119     }
120
121     bool set(int i, const T& e)   //  O(n)
122     {
123         bool ret = ((0 <= i) && (i < m_length));
124
125         if( ret )
126         {
127             position(i)->next->value = e;
128         }
129
130         return ret;
131     }
132
133     T get(int i) const
134     {
135         T ret;
136
137         if( get(i, ret) )
138         {
139             return ret;
140         }
141         else
142         {
143             THROW_EXCEPTION(IndexOutOfBoundsException, "Invalid parameter i to get element ...");
144         }
145
146         return ret;
147     }
148
149     bool get(int i, T& e) const    // O(n)
150     {
151         bool ret = ((0 <= i) && (i < m_length));
152
153         if( ret )
154         {
155             e = position(i)->next->value;
156         }
157
158         return ret;
159     }
160
161     int find(const T& e) const    //  O(n)
162     {
163         int ret = -1;
164         int i = 0;
165
166         SmartPointer<Node> node = m_header.next;
167
168         //while( node )
169         while( node.isNull() )
170         {
171             if( node->value == e )
172             {
173                 ret = i;
174                 break;
175             }
176             else
177             {
178                 node = node->next;
179                 i++;
180             }
181         }
182
183         return ret;
184     }
185
186     int length() const   // O(1)
187     {
188         return m_length;
189     }
190
191     void clear()    //  O(n)
192     {
193         //while( m_header.next )
194         while( m_header.next.isNull() )
195         {
196             //Node* toDel = m_header.next;
197             SmartPointer<Node> toDel = m_header.next;
198
199             m_header.next = toDel->next;
200
201             m_length--;
202
203             // destroy(toDel);
204         }
205
206         // m_length = 0;
207     }
208
209     bool move(int i, int step = 1)
210     {
211         bool ret = (0 <= i) && (i < m_length) && (step > 0);
212
213         if( ret )
214         {
215             m_current = position(i)->next;
216             m_step = step;
217         }
218
219         return ret;
220     }
221
222     bool end()
223     {
224         //return (m_current == NULL);
225         return m_current.isNull();
226     }
227
228     T current()
229     {
230         if( !end() )
231         {
232             return m_current->value;
233         }
234         else
235         {
236             THROW_EXCEPTION(InvalidOperationException, "No value at current position ...");
237         }
238     }
239
240     bool next()   //每次移动step步
241     {
242         int i = 0;
243
244         while((i < m_step) && !end())
245         {
246             m_current = m_current->next;
247             i++;
248         }
249
250         return (i == m_step);
251     }
252
253     ~LinkList()   //  O(n)
254     {
255         clear();
256     }
257 };
258
259 }
260
261 #endif // LINKLIST_H

测试程序如下:

 1 #include <iostream>
 2 #include "LinkList.h"
 3
 4 using namespace std;
 5 using namespace DTLib;
 6
 7
 8 int main()
 9 {
10     LinkList<int> list;
11
12     for(int i = 0; i < list.length(); i++)
13     {
14         list.insert(i);
15     }
16
17     for(list.move(0); !list.end(); list.next())
18     {
19         cout << list.current() << endl;
20     }
21
22     return 0;
23 }

运行结果如下:

程序直接崩溃了。

我们的SmartPointer设计中,一片堆空间最多只能由一个指针标识,但是我们设计的和遍历有关的函数,例如move、end、current、next,在遍历时一片堆空间会由多个指针指向,所以程序崩溃了。

改进方案:

我们需要创建一个中间类pointer,并且它还有两个子类。

SharedPointer支持一片堆空间由多个指针指向,也支持自动释放。

在设计上做了改动,所以SmartPointer也得做改动。

pointer类中的析构函数是纯虚函数,因为pointer是一个抽象父类,需要由子类继承才能生成对象。

Object的析构函数就是纯虚的,所以pointer中就没有必要再写一遍了。

只要pointer没有实现自己的析构函数,那么它就还是一个抽象类。

原文地址:https://www.cnblogs.com/wanmeishenghuo/p/9652199.html

时间: 2024-10-29 19:05:42

第二十七课 再论智能指针(上)的相关文章

第二十八课 再论智能指针(下)

多个智能指针指向同一片堆空间的需求是巨大的. 计数变量也是在堆空间里面定义的,它的生命周期和对象的生命周期相同. 添加SharedPointer.h文件: 1 #ifndef SHAREDPOINTER_H 2 #define SHAREDPOINTER_H 3 4 #include <cstdlib> 5 #include "Pointer.h" 6 #include "Exception.h" 7 8 namespace DTLib 9 { 10 1

第28课 再论智能指针(下)

1. SharedPointer的设计 (1)使用类模板,通过计数机制标识堆内存 (2)堆内存被指向时,refCount++ (3)指针被置空时:refCount- (4)当refCount == 0时,释放堆内存 2. 计数机制原理剖析 3. SharedPointer类的声明 template <typename T> class SharedPointer : public Pointer<T> { protected: int m_refCount; //计数机制成员 pu

再论智能指针(上)

0.引言: 目的:使用智能指针替代LinkList中的原生的指针, 限制:但是我们的智能指针设定了只能单个指针指向某一片堆空间 1. 智能指针的继承层次结构 (1)Pointer是智能指针的抽象父类(模板) ①纯虚析构函数:virtual ~Pointer()=0; ②重载operator->() ③重载operator*() (2)类的声明 1 template <typename T> 2 class Pointer : public Object 3 { 4 protected:

再谈智能指针

http://www.cnblogs.com/lewiskyo/p/4214592.html  之前写过一篇文章介绍智能指针,并且简单实现了auto_ptr. 里面提到 auto_ptr 不能做为Stl容器的元素,原因具体是 http://www.360doc.com/content/14/0429/16/1317564_373230218.shtml 简要来说就是在对Stl容器元素进行复制构造时,不能改变原来的值(const T2& value),而auto_ptr在复制构造的时候,一定会修改

第二十七课

第一单元语法部分        Vて行く Vて来る「行く.来る」有方向性.以某物为参照物.接在「Vて」形式后面,表示完成V动作后进行方向性移动.     Vていく    ①表示移动时的状态.“…着去,…去”        例:学校まで走っていこう.    ②表示远离说话人而去.         例:船はどんどん遠くに離れていった.    ③表示做完某动作行为再去.“…了再去”        例:母の誕生日だから.途中で花を買って行きました.    ④以某一时间为基准,变化或动作继续下去.“…下去

第二十七课:滚轮事件,mouseenter与mouseleave事件的修复

滚轮事件 jQuery核心库没有对mousewheel事件的差异性进行处理,但作为一个常用的事件,本文讲解一下. mousewheel事件只有火狐浏览器不支持.mousewheel用于取得滚动距离的属性名为event.wheelDelta,往上滚一圈是120,往下滚一圈是-120.在IE6-8下,window无法绑定mousewheel事件,Opera,Safari,Chrome可以. 火狐下使用DOMMouseScroll来代替mousewheel事件.用于取得滚动距离的属性名为event.d

Spring入门第二十七课

声明式事务 直接上代码: db.properties jdbc.user=root jdbc.password=logan123 jdbc.driverClass=com.mysql.jdbc.Driver jdbc.jdbcUrl=jdbc:mysql://localhost:3306/spring jdbc.initPoolSize=5 jdbc.maxPoolSize=10 applicationContext.xml <?xml version="1.0" encodin

ParisGabriel:Python全栈工程师(0基础到精通)教程 第二十七课(类变量、方法、继承、覆盖)

ParisGabriel 每天坚持手写  一天一篇  决定坚持几年 为了梦想为了信仰  开局一张图 Python人工智能从入门到精通 补充: 实例方法都是操作实例对象的 属于此类对象的方法 实例变量 添加/修改属性: 对象.属性名 = 表达式 删除: del 对象.属性名 类 |          对象 | 实例 class  object     instance 类的本质上也是对象 类可以创建此类对象 ---------------------------------------------

linux学习笔记-第二十七课-tamcat与resin

一.tomcat 1. 安装JDK [[email protected] src]# tar -zxvf jdk-7u79-linux-i586.tar.gz # 编辑初始化信息脚本 [[email protected] src]# mv jdk1.7.0_79  /usr/local/jdk1.7.0_79 [[email protected] src]# vim /etc/profile.d/java.sh JAVA_HOME=/usr/local/jdk1.7.0_79 JAVA_BIN=