第六十讲 迭代器(5)

关于容器指针的基础知识已经说的差不多,现在该是我们扩展的时候了,回复第五十七讲,留给大家一个练习,我们以填坑之名,来扩展我们的所谓的容器(其实就是My_Array了,因为我们目前从序列容器入手,而序列容器又和数组是一个样子的),让大家回头去看那个问题显得有些复杂,所以我们这里给大家再重复一遍问题:
——————————
My_Array<int>m_Array;


for(int i=0;

i<N;

i++)

m_Array.push_back(i);


for(int i=0;

i<N;

i++)

cout<<m_Array[i]<<"

"

;


——————————

我们要让这段代码输出如下的结果:
——————————-
0 1 2 3 4 5 6 7 8 9…………N
——————————–

这就是我们的问题,如果大家都知道STL的话,就会明白,其实我们的容器都有这个方法(push_back()),push_back的功能简单点说,就是把一个元素压入容器中,我们都知道在vector等序列容器的这种方法永远可以存入数据,直到内存消耗完成,所以,当我们调用push_back的时候其实也就悄悄的改变了数组的大小。

好吧,废话不多说了,直接开始吧,我们我们的底层数据继续扩充,我们再添加一个数据成员,用来表示数组的容量:
—————————-
unsigned m_Cap;


—————————-
这样一来,我们的构造函数可以重新这样写:
——————————-

My_Array_Data(unsigned n=0):

m_Size(n),m_Cap(2*n+10),Data(new T[m_Cap]),m_Count(1)
{
}
——————————–

或许有些朋友会问,为什么不用m_Size来初始化m_Cap呢?当然他们有这样的理由,因为在vector等序列容器中,m_Cap和m_Size确实存在关系的,据相关的研究表示,m_Cap等于1.5倍m_Size是最为合理的,所以,他们有理由用m_Size去初始化m_Cap,但是现在我告诉大家,初始化的时候我们最好是不要用m_Size去初始化m_Cap,因为这样会给我们带来很多麻烦。

接下来我们再来定义一个Cap函数,通过这个函数,我们可以取得该容器的最大容量:
———————————
unsigned Cap(){

return m_Cap;


}
———————————

当我们push_back的时候,当发现m_Size == m_Cap的时候,说明容器已经满了,那么为了能够继续push_back,我们就的扩充容器,又由于序列容器是序列的,所以很多时候会在其他地方开辟出一块内存,再把当前数据转存过去,然后继续push_back。知道这些后我们可以轻松的完成这个函数:
———————————

void Push_Back(const T&

t){

if(this->Size() == this->Cap()){

unsigned
temp = 2*m_Size;


T* old = Data;


Data = new T[temp];


copy(old,m_Size);

//这是我们前面说到的一个辅助函数

delete old;


m_Cap = temp;


}

Data[m_Size] = t;


m_Size++;


}
——————————–

现在,我们上面的程序可以运行了,我们来测试一下:
—————————–
#include "

My_Point.h"


using namespace My_Code;

int main()
{

My_Array<int>a;



for(int i=0;

i<10000;

i++)

a.Push_Back(i);


for(int i=0;

i<10000;

i++)

cout<<a[i]<<"

"

;


cout<<endl;


cout<<a.Cap()<<endl;


return 0;


}
————————————

输入如同封面上的,因为最近微信公众账号这东西出了点bug,不能添加图片。下一讲我们再来深入研究一下其他的东西。

======================
回复D直接查看目录


原文始发于微信公众号(

C/C++的编程教室

):第六十讲 迭代器(5)

|

发表评论