C++学习笔记(七)----向量(vector)的实现
做了几道zoj的题目,感到基础知识都忘得差不多了,很有必要重新学习,选了两本书,一本是大学时的课本《数据结构(C语言版)》,循序渐进,由浅入深,相信学过数据结构的都看过或者听说过这本书.还有一本是在网上找到的,书名是《数据结构和算法分析 C++描述》,这本书文字比较简练,但其中包含的信息量很大,读起来很有味道,也让人很有激情,很好.
现在分析一下《数据结构和算法分析 C++描述》中图3-7,3-8的代码,看看能从这段代码中找到哪些需要注意的要点.
代码如下:
2 class Vector
3 {
4 public:
5 explicit Vector( int initSize = 0 )
6 : theSize( initSize ), theCapacity( initSize + SPARE_CAPACITY )
7 { objects = new Object[ theCapacity ]; }
8 Vector( const Vector & rhs ) : objects( NULL )
9 { operator=( rhs ); }
10 ~Vector( )
11 { delete [ ] objects; }
12
13 const Vector & operator= ( const Vector & rhs )
14 {
15 if( this != &rhs )
16 {
17 delete [ ] objects;
18 theSize = rhs.size( );
19 theCapacity = rhs.theCapacity;
20
21 objects = new Object[ capacity( ) ];
22 for( int k = 0; k < size( ); k++ )
23 objects[ k ] = rhs.objects[ k ];
24 }
25 return *this;
26 }
27
28 void resize( int newSize )
29 {
30 if( newSize > theCapacity )
31 reserve( newSize * 2 + 1 );
32 theSize = newSize;
33 }
34
35 void reserve( int newCapacity )
36 {
37 if( newCapacity < theSize )
38 return;
39
40 Object *oldArray = objects;
41
42 objects = new Object[ newCapacity ];
43 for( int k = 0; k < theSize; k++ )
44 objects[ k ] = oldArray[ k ];
45
46 theCapacity = newCapacity;
47
48 delete [ ] oldArray;
49 }
50
51
52 Object & operator[]( int index )
53 { return objects[ index ]; }
54 const Object & operator[]( int index ) const
55 { return objects[ index ]; }
56
57 bool empty( ) const
58 { return size( ) == 0; }
59 int size( ) const
60 { return theSize; }
61 int capacity( ) const
62 { return theCapacity; }
63
64 void push_back( const Object & x )
65 {
66 if( theSize == theCapacity )
67 reserve( 2 * theCapacity + 1 );
68 objects[ theSize++ ] = x;
69 }
70
71 void pop_back( )
72 { theSize--; }
73
74 const Object & back ( ) const
75 { return objects[ theSize - 1 ]; }
76
77 typedef Object * iterator;
78 typedef const Object * const_iterator;
79
80 iterator begin( )
81 { return &objects[ 0 ]; }
82 const_iterator begin( ) const
83 { return &objects[ 0 ]; }
84 iterator end( )
85 { return &objects[ size( ) ]; }
86 const_iterator end( ) const
87 { return &objects[ size( ) ]; }
88
89 enum { SPARE_CAPACITY = 16 };
90
91 private:
92 int theSize;
93 int theCapacity;
94 Object * objects;
95 };
1.第1行,template ['templit]关键字后接模板形参表,表明这里定义的Vector是一个类模板,而不是一个类,Vector<int>
2.第5行,将构造函数声明为explicit [ik'splisit] ,是为了抑制由构造函数定义的隐式转换,如果这里没有explicit,那么下面的语句:
Vector
...
vec=2;
将是合法的,"="右边的2将被这个不带explicit的构造函数隐式转换为一个Vector类型的临时变量,然后再通过operator=复制给vec.但这可能不是我们想要的结果,为了避免错误,在某些情况下,我们给单形参构造函数加上关键字explicit,这样的话上面的语句就不能编译通过了,vec=2要改为vec=vec(2).关于explicit的更多论述,可以参见《C++ Primer》第12.4.4小节.
3.第6行,是构造函数的初始化列表.关于构造函数的初始化列表,有两个要点.第一,即使列表为空,没有初始化式,构造函数也会先初始化每个成员再进入函数体,这时初始化的规则与初始化变量相同,由此得知第二个要点:如果类的成员本身是一个没有默认构造函数的类类型,或者成员是const、引用类型,这样的成员必须在构造函数初始化列表中进行初始化.详见《C++ Primer》第12.4.1小节.
4.第7行和第11行,第7行的new返回一个指向Object类型数组的指针,而通过new关键字分配的存储空间需要通过delete操作将其删除.反之,如果某个对象不是通过new操作动态创建获得的,那么它就不能由delete操作释放,事实上在这些对象的生命期结束之后,编译器会自动释放空间.这两行是一个特例,他们不是动态创建和释放单个对象,而是动态创建和释放数组,所以我们看到第11行使用了"delete []"操作符.
5.第8行至第26行分别定义了Vector的复制构造函数,析构函数和重载赋值操作符.
6.第52至55行,这里定义了重载下标操作符的两个版本,由于成员函数的定常性是(即函数名后是否有const关键字)是签名的一部分,因此我们可以使用访问函数的operator[]版本返回const引用,而修改函数版本返回一般引用.