c++ STL 学习记录 草稿。

非常丑陋的尝试实现stl。慢慢修改吧。

1)简单实现 vector和list。

2)思索如何开始编写算法。

  1,所有容器继承一个抽象容器。那么算法就可以使用抽象基类的next方法来遍历元素。 容器间耦合太高,放弃。

  2,所有容器的元素T继承一个基类,算法使用基类的next方法来遍历元素。应该是可以的。做到一半,实现多态时,必须太多指针样子,好像跟stl的使用相差太远。看书发现stl是用模板模拟多态。或者说是模板的正宗,优雅的多态形式。

  3,使用模板的更优雅的多态思想来实现容器的迭代器。

3)后面的改进,在于迭代器修改为pointerlike的类。还有书上谈到把各自的迭代器放入到容器类中?以免迭代器暴露太多容器细节。为什么不可以用容器的public方法?

第一版

main

#include <iostream>
#include "myvecotr.h"
#include "al.h"
#include <algorithm>
#include <vector>
#include "mylist.h"

using namespace std;

class Book
{
public:
    Book(int _id,const string& _name):id(_id),name(_name){}
    int GetInt()
    {
        return id;
    }
    string GetName()
    {
        return name;
    }

    bool operator==(const Book& rhg)
    {
        bool ret=false;
        if(rhg.id==this->id && rhg.name==this->name)
        {
            ret=true;
        }
        return ret;
    }

private:
    int id;
    string name;
};

int main()
{
    Book cc(1,"c++");
    Book cc2(5,"c");
    Book cc3(3,"c#");

    cout<<"*************stl*********************"<<endl;
    vector<Book> books2;
    books2.push_back(cc);
    books2.push_back(cc2);
    books2.push_back(cc3);

    vector<Book>::iterator myit=books2.begin();
    cout<<myit->GetName()<<endl;

    cout<<"*************list*********************"<<endl;
    MyList<Book> bookList;
    bookList.push_back(cc);
    bookList.push_back(cc2);
    bookList.push_back(cc3);

    cout<<bookList.GetHead()->GetV()->GetName()<<endl;

    ListIterator<Book> FF= myFind(bookList.getFirstIterator(),bookList.getIterator(2),cc3);
    cout<<FF.GetP()->GetV()->GetName()<<endl;

    myVector<Book> books;
    books.push_back(cc);
    books.push_back(cc2);
    books.push_back(cc3);

    cout<<"*************vector*********************"<<endl;
    myVector<Book>::iterator rnt=myFind(books.GetBegin(),books.GetEnd(),cc2);

    cout<<rnt->GetName()<<endl;
    return 0;
}

mylist.h

#ifndef MYLIST_H_INCLUDED
#define MYLIST_H_INCLUDED
#include <memory>
#include <stdexcept>
#include <iostream>

using namespace std;

////////////////////listnode.
template<typename T>
class ListNode
{
public:
    ListNode( T*,ListNode*);
    void SetNext(ListNode*);
    ListNode* GetNext();
    bool IsEmpty();
    T* GetV();

private:

    T* value;
    ListNode* next;
};

template<typename T>
ListNode<T>::ListNode( T* v,ListNode* n):value(v),next(n){}

template<typename T>
void ListNode<T>::SetNext(ListNode* n)
{
    next=n;
}

template<typename T>
ListNode<T>* ListNode<T>::GetNext()
{
    return next;
}

template<typename T>
bool ListNode<T>::IsEmpty()
{
    if(value==0 && next==0)
    {
        return true;
    }
    else
    {
        return false;
    }
}

template<typename T>
T* ListNode<T>::GetV()
{
    return value;
}

/////////////////////////////////list iterator

//1)必须有正确的+号操作和!=操作.2)必须有全局的元素和迭代器==的重载.

template<typename T>
class ListIterator
{
public:
    ListIterator(ListNode<T>* v):myP(v){}
    ListIterator operator+(int index)
    {
        ListNode<T>* pListNode=myP;
        for(int i=0;i!=index;++i)
        {

            if(pListNode->GetNext()!=0)
            {
                pListNode=pListNode->GetNext();
            }
            else
            {
                break;
            }
        }
        return ListIterator(pListNode);
    }

    bool operator!=(const ListIterator& rht)
    {
        return myP!=rht.myP;
    }
    ListNode<T>* GetP()
    {
        return myP;
    }
private:
    ListNode<T>* myP;
};

template<typename T>
bool operator==( ListIterator<T>& lht,  T& rht)
{
    return rht==*(lht.GetP()->GetV());
}

/////////////////////////////////mylist

template<typename T>
class MyList
{
public:
    MyList():head(0),size(0){}
    void push_back(const T& v)
    {
        ListNode<T>* tempNode=new ListNode<T>(new T(v),0);
        if(head==0)
        {
            head=tempNode;
            ++size;
        }
        else
        {
            ListNode<T>* temp=head;
            while(temp->GetNext()!=0)
            {
                temp=temp->GetNext();
            }
            temp->SetNext(tempNode);
            ++size;
        }
    }

    ListNode<T>* GetHead()
    {
        return head;
    }

    ListIterator<T> getFirstIterator()
    {
        return ListIterator<T>(head);
    }

    ListIterator<T> getIterator(int i)
    {
        ListNode<T>* rnt=0;
        if(i>=0)
        {
            ListNode<T>* temp=head;

            for(int index=0;index!=i;++index)
            {
                ListNode<T>* temp2=temp->GetNext();
                if(temp2!=0)
                {
                    temp=temp2;
                    cout<<temp<<endl;
                }
                else
                {
                    break;
                }
            }

            rnt=temp;
        }

        return ListIterator<T>(rnt);
    }

    ~MyList()
    {
        ListNode<T>* temp=head;
        while(temp!=0)
        {
            ListNode<T>* del=temp;
            temp=temp->GetNext();
            delete del->GetV();
            delete del;
        }
    }
private:
    int size;
    ListNode<T>* head;
};

#endif // MYLIST_H_INCLUDED

myvector.h

#ifndef MYVECTOR_H_INCLUDED
#define MYVECTOR_H_INCLUDED
//allocator<T> a;                           定义一个T类型的allocator对象。
//a.allocate(n);                            申请n个T大小的,未分配的空间。类似(T*) malloc(sizeof(T)*n)
//a.deallocate(p,n)                         释放内存,p为T*,n为释放的T类型对象的数量。注意:T类型对象本身,如有需要释放的资源,必须先释放,a.deallocate(p,n)只是释放对象本身的内存,而对象的建立又额外申请的资源,需要另外处理。
//a.construct(p,t)                          复制构造,用t来复制构造。相当于 new (p) T(t),这个是placement new的用法  new(place_address) type(initializer-list)
//a.destroy(p)                   调用pd对象的析构函数。
//uninitialized_copy(startit,endit,it)      startit,endit :要复制的开始迭代器地址和结束地址。it:要复制的迭代器地址。
//uninitialized_fill(startit,endit,obj)     startit,endit :要复制的开始迭代器地址和结束地址。it:要复制的对象。 使用复制构造函数填充内存
//uninitialized_fill_n(startit,endit,obj,n) startit,endit :要复制的开始迭代器地址和结束地址。it:要复制的对象。 n,要复制的数量。 使用复制构造函数填充内存

//因为是模板,有类型参数,类的方法编译的时候,不能确定所占用的栈大小.必须使用的时候才能确定,而且不同的T类型,有不同的方法地址.所以申明定义放到一起
#include <memory>
#include <stdexcept>
#include <iostream>
#include "myitertor.h"
using namespace std;

template<typename T>
class myVector{
public:

    //如果分配错误呢?
    myVector():pbegin(myalloc.allocate(defautlSize)),pend(pbegin),pcapcity(pbegin+defautlSize),Vsize(0),Vcapcity(defautlSize){}

    typedef T* iterator;

    void push_back(const T& _obj)
    {
        if(pend>=pcapcity)
        {
            T* pTempAlloc=myalloc.allocate(Vcapcity*2);
            T* pPrep=pbegin;
            if(pTempAlloc!=0)
            {
                uninitialized_copy(pbegin,pend,pTempAlloc);
                pbegin=pTempAlloc;
                pend=pbegin+Vsize;
                pcapcity=pbegin+(Vcapcity*2);
                Vsize=Vsize;
                Vcapcity+=Vcapcity;

                //清理原资源.
                destroyS(pPrep,pPrep+Vsize,pPrep+Vsize);
            }
            else
            {
                throw runtime_error("error allocator!");
            }
        }

        myalloc.construct(pend,_obj);
        ++pend;
        ++Vsize;
    }
    void erase(unsigned int index)
    {
        if(index>=0&& index<Vsize)
        {
            myalloc.destroy(pbegin+index);//手动调用对象析构
            for(int i=index+1;i!=Vsize;++i)//往前覆盖.最后一个对象占用的内存,不管了.pend往前移动就好.
            {
                uninitialized_copy(pbegin+i,pbegin+i+1,pbegin+i-1);
            }
            --Vsize;
            --pend;
        }
        else
        {
            throw runtime_error("index over range.");
        }

    }
    ~myVector()
    {
        destroyS(pbegin,pend,pcapcity);
    }
    myVector(const myVector& _obj)
    {
        pbegin=myalloc.allocate(_obj.Vcapcity);
        pend=pbegin+_obj.Vsize;
        pcapcity=pbegin+_obj.Vcapcity;
        Vsize=_obj.Vsize;
        Vcapcity=_obj.Vcapcity;
        uninitialized_copy(_obj.pbegin,_obj.pend,pbegin);
    }

    myVector& operator=(const myVector& _obj)
    {
        if(&_obj!=this)
        {
            destroyS(pbegin,pend,pcapcity);
            pbegin=myalloc.allocate(_obj.Vcapcity);
            pend=pbegin+_obj.Vsize;
            pcapcity=pbegin+_obj.Vcapcity;
            Vsize=_obj.Vsize;
            Vcapcity=_obj.Vcapcity;

            uninitialized_copy(_obj.pbegin,_obj.pend,pbegin);
        }
        return *this;
    }

    int size()
    {
        return pend-pbegin;
    }

    int capcity()
    {
        return pcapcity-pbegin;
    }

    void showInfo()
    {
        cout<<"pbegin:"<<(void *)pbegin<<". size:"<<Vsize<<". capcity"<<Vcapcity<<". pend:"<<(void *)pend<<endl;
        T* pb=pbegin;
        for(pb;pb!=pend;++pb)
        {
            cout<<*pb<<endl;
        }
    }

    T& operator[](int index)
    {
        return *(pbegin+index);
    }

    T* GetBegin()
    {
        return pbegin;
    }
    T* GetEnd()
    {
        return pend;
    }

private:
    static allocator<T> myalloc;
    const static int defautlSize=3;
    T* pbegin;
    T* pend;
    T* pcapcity;
    unsigned int Vcapcity;
    unsigned int Vsize;

    void destroyS(T* PS,T* PE,T* PC)
    {
        T* pb=PS;
        for(pb;pb!=PE;++pb)
        {
            myalloc.destroy(pb);//仅仅调用析构函数.
        }
        myalloc.deallocate(PS,PC-PS);
    }

};

//int book::pid=6
template<typename T>
allocator<T> myVector<T>::myalloc=allocator<T>();

template<typename T>
bool operator==(T* a,T v)
{
    bool rnt;
    if(*a==v)
    {
        rnt=true;
    }
    else
    {
        rnt=false;
    }
    return rnt;
}

#endif // MYVECTOR_H_INCLUDED

al.h

#ifndef AL_H_INCLUDED
#define AL_H_INCLUDED

#include "myitertor.h"

//1)必须有正确的+号操作和!=操作.2)必须有全局的元素和迭代器==的重载.

template<typename T,typename MyInputIterator>
MyInputIterator myFind(MyInputIterator start,MyInputIterator end, T& value)
{
    for(start;start!=end;start=start+1)
    {
        if(start==value)//
        {
            break;
        }
    }
    return start;
}

#endif // AL_H_INCLUDED
时间: 2024-08-10 19:18:09

c++ STL 学习记录 草稿。的相关文章

stl学习记录

Effective STL 中文版学习记录 条款4 判断容器是否为空 使用empty而不是size().size()操作在实现上不是一个时间常数操作条款5 尽量使用区间成员函数代替它们的单元素兄弟.STL实现中,区间范围显示比单个循环操作更优化 条款7:当使用new得指针的容器时,记得在销毁容器前delete那些指针vc2008下 运行代码 可以看到 该程序内存不断增加// 1111111.cpp : 定义控制台应用程序的入口点.// #include "stdafx.h" #incl

STL学习记录:链表

直接百度链表的话,其实和真正用起来的STL链表差的挺远的(毕竟有些情况能用就行~),还是自己写一下记录一下STL里链表具体用法吧 #include <bits/stdc++.h> using namespace std; int main () { //1. 定义 //list<数据类型> 链表名称 list<int> test; list<int>::iterator iter=test.begin(); //2. 增删改查 //增加 test.push_

stl学习记录(2)

#include <iostream> #include <utility> #include <tuple> #include <complex> #include <string> using namespace std; // 代码 改编自 C++标准库——自学教程与参考手册 英文第二版 //==================================== // tuple io template <int IDX,int M

STL学习记录:栈与队列

首先是栈的基本操作,也就这些了 #include <bits/stdc++.h> using namespace std; int main () { stack<int> test;//声明方式:stack <数据类型> 名称 test.push(2); //向栈中压入2 test.top()=1; //也可以直接改变栈顶的值 test.pop(); //弹出栈顶部的值 if (test.empty())//如果栈空,返回true cout<<"

STL学习之路之仿函数

STL中的仿函数(或者叫做函数对象):可以实现类似于函数一样的类型,函数最直接的调用形式就是:返回值 函数名(参数列表),仿函数实现了operator()操作符,使用类似于函数. 同时,STL还为仿函数提供了强大的配接器,也就是适配器Adapters,这些适配器本身也属于仿函数,调用方式同样类似于函数.更进一步,这些适配器可以和仿函数.函数.适配器再进行绑定.组合.适配,完成更加复杂的功能. 这部分应该是STL中最简单的部分,实现也比较简单.另外C++11标准对这部分调整比较大,我们先不考虑.暂

STL学习_配接器篇

STL学习_配接器篇 定义 配接器(Adapter)在STL组件的灵活组合运用功能上,扮演着轴承.转换器的角色.它事实上是一种设计模式.即将一个class的接口转换为另一个class的接口,使原本因接口不兼容而不能合作的classes,可以一起运作. 分类 STL所提供的各种适配器中,改变仿函数(functors)接口者,称为function adapter:改变容器(containers)接口者,称为container adapter:改变迭代器(iterators)接口者,称为iterato

【程序员编程艺术】学习记录2:左旋转字符串之循环移位法

[程序员编程艺术]学习记录2:左旋转字符串之循环移位法 GCD算法:(辗转相除法/欧几里得算法) gcd是求最大公约数的算法,作为TAOCP第一个算法 gcd算法流程: 首先给定两个整数m,n(m大于等于n)如果小于则直接交换再处理 ①求余数 r=m%n ②假如r=0,算法结束,n即为所求 否则,重新令m <- n, n <-r 之后循环 <<<<<<<<<<<<<<<<<<<&l

Python学习记录-2016-12-17

今日学习记录 模块: import os#导入os模块 import sys#导入sys模块 os.system("df -h")#执行df -h命令 cmd_res = os.popen("df -h").read()#将命令的返回结果赋值给cmd_res,如果不加入.read()会显示命令的返回加过在内存的位置 print(sys.path)#显示系统变量路径,一般个人模块位于site-packages下,系统模块位于lib下 print(sys.argu[2]

Objc基础学习记录5

NSMutableString类继承的NSString类. NSMutableString是动态的字符串. 1.appendingString 方式: 向字符串尾部添加一个字符串. 2.appendingFormat:可以添加多个类型的字符串. int,chat float,double等 3.stringWithString 创建字符串, 4.rangeOfString 返回str1在另一个字符串中的位置. 5.NSMakeRange(0,3) 字符串0位到3位. 6.deleteCharac