第二次修改:

1)熟悉基本的模板编程,头文件和定义必须放到一起。

2)熟悉内存管理模板类 allocator<T>。

1.使用标准库的内存管理类 allocator<T>  代替原来c的malloc和free。 可以给无默认构造函数的类分配指定空间。
2.第一次写的时候,只free vectore元素占用内存, 没有调用元素的析构函数,那个时候还没有搞清楚,析构什么时候会调用。free 是无法调用析构函数的。
3.模板类的编译问题: 因为是模板类,有类型参数,类的方法编译的时候,不能确定所占用的栈大小.必须使用的时候才能确定,而且不同的T类型,有不同的方法地址.所以申明定义放到一起
4.myalloc.destroy(pb);//仅仅调用析构函数.
  5)void *memset(void *s, int ch, size_t n);
  函数解释:将s中当前位置后面的n个字节 (typedef unsigned int size_t )用 ch 替换并返回 s 。
#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>
using namespace std; template<typename T>
class myVector{
public:
//如果分配错误呢?
myVector():pbegin(myalloc.allocate(defautlSize)),pend(pbegin),pcapcity(pbegin+defautlSize),Vsize(),Vcapcity(defautlSize){} void push_back(const T& _obj)
{
if(pend>=pcapcity)
{
T* pTempAlloc=myalloc.allocate(Vcapcity*);
T* pPrep=pbegin;
if(pTempAlloc!=)
{
uninitialized_copy(pbegin,pend,pTempAlloc);
pbegin=pTempAlloc;
pend=pbegin+Vsize;
pcapcity=pbegin+(Vcapcity*);
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>=&& index<Vsize)
{
myalloc.destroy(pbegin+index);//手动调用对象析构
for(int i=index+;i!=Vsize;++i)//往前覆盖.最后一个对象占用的内存,不管了.pend往前移动就好.
{
uninitialized_copy(pbegin+i,pbegin+i+,pbegin+i-);
}
--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;
}
} private:
static allocator<T> myalloc;
const static int defautlSize=;
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>(); #endif // MYVECTOR_H_INCLUDED

实现功能基本:

插入元素,pushback.
引用构造,
copy功能.
按索引返回.
删除索引位置元素.

备注:
//默认大小为32个数据元素。新插入不够,空间翻倍,为32,64,128。。。。
//引用构造,新对象和引用对象一致。 copy复制,先检测空间,若空间不够,调整为右直的大小。
//注意capcity 的const。是为了MyVector2(const MyVector2<T>&);

有几个新知识点:

1)placement new 的写法 。给 一个已经申请内存的空间。放入对象值。new是先申请后放入。这里省去申请。

new(endP) T(*s_iterator);//placement new .

2)int类型的数据与unsigned int类型的数据进行比较时会把int类型的数据转换为unsigned int 类型的数据,然后再进行比较。

所以 int -1会大于 unsigned 0.

3)pushback 中。空间 不够 。要申请空间。注意不要建立临时对象,再吧临时对象的数据给左值。 因为临时对象离开pushback韩素 会析构。导致左值的结果被删除了。

测试发现有问题的同学,这里看看自己有没有犯同样的错误。

所以直接申请空间。再把地址给左值就好了。

myvector2.h

#ifndef MYVECTOR2_H_INCLUDED
#define MYVECTOR2_H_INCLUDED #include "malloc.h"
#include <iostream>
using namespace std;
//实现功能基本:插入元素,pushback.
//引用构造,
//copy功能.
//按索引返回.
//删除索引位置元素. //默认大小为32个数据元素。新插入不够,空间翻倍,为32,64,128。。。。
//引用构造,新对象和引用对象一致。 copy复制,先检测空间,若空间不够,调整为右直的大小。
//注意capcity 的const。是为了MyVector2(const MyVector2<T>&); template<typename T>
class MyVector2{
public:
MyVector2();
MyVector2(const MyVector2<T>&);
MyVector2<T> & operator=(const MyVector2<T>&);//copy操作,左直是一定存在的。所以可以返回引用。
int PushBack(const T&);
T& operator[](unsigned int);
unsigned int size()const;
unsigned int capcity()const;//注意capcity 的const。是为了MyVector2(const MyVector2<T>&);中,参数是const.而且还调用了参数的capcity()方法.所以方法必须const. void erace(unsigned int); ~MyVector2()
{
del();
} private:
T* firstP;
T* endP;
T* CapicityP;
static const unsigned int stepsize=32; void addEnd();
void del(); MyVector2(unsigned int);//private 指定模板数据类型数量来初始化类.
}; template<typename T>
MyVector2<T>::MyVector2():firstP((T*)malloc(sizeof(T)*stepsize)),endP(firstP)
{
CapicityP=firstP+stepsize;//不知为什么,如果防入初始化.CapicityP是莫名的数据.
cout<<"c malloc:"<<firstP<<endl;
} template<typename T>
MyVector2<T>::MyVector2(const MyVector2<T>& _rhs):firstP((T*)malloc(sizeof(T)*_rhs.capcity())),endP(firstP)
{
cout<<"ref malloc:"<<firstP<<endl;
CapicityP=firstP+_rhs.capcity();
T* s_iterator=_rhs.firstP;
for(s_iterator;s_iterator!=_rhs.endP;++s_iterator)
{
new(endP) T(*s_iterator);//placement new .
++endP;
}
} template<typename T>
MyVector2<T> & MyVector2<T>::operator=(const MyVector2<T>& _rhs)
{
if(this->capcity()>=_rhs.size())
{
this->endP=this->firstP; T* s_iterator=_rhs.firstP;
for(s_iterator;s_iterator!=_rhs.endP;++s_iterator)
{
new(endP) T(*s_iterator);//placement new .
++endP;
}
}
else
{
del(); T* TempfirstP=(T*)malloc(sizeof(T)*_rhs.capcity());
T* TempendP=TempfirstP;
T* TempCapcityP=TempfirstP+(_rhs.capcity()); cout<<"copy malloc:"<<TempfirstP<<endl; T* s_iterator=_rhs.firstP;
for(s_iterator;s_iterator!=_rhs.endP;++s_iterator)
{
new(TempendP) T(*s_iterator);//placement new .
++TempendP;
} firstP=TempfirstP;
endP=TempendP;
CapicityP=TempCapcityP; }
return *this;
} template<typename T>
MyVector2<T>::MyVector2(unsigned int _tsize):firstP((T*)malloc(sizeof(T)*_tsize))
{
endP=firstP;
CapicityP=firstP+_tsize;
} template<typename T>
void MyVector2<T>::erace(unsigned int _index)
{
//endp 减1。index以下数据望上移动。
//:int类型的数据与unsigned int类型的数据进行比较时会把int类型的数据转换为unsigned int 类型的数据,然后再进行比较。
//坑太多。。。。这里size 为0的花。size-1为-1。按照规则会比无符号的0大。。。
if(_index>=0 && _index<=this->size()-1 && this->size()>0)//
{ T* titerator=this->firstP+_index+1; for(titerator;titerator!=this->endP;++titerator)
{
new(this->firstP+_index) T(*(this->firstP+_index+1));
}
--endP;
}
} template<typename T>
unsigned int MyVector2<T>::size()const
{
return endP-firstP;
} template<typename T>
unsigned int MyVector2<T>::capcity()const
{
return CapicityP-firstP;
} template<typename T>
void MyVector2<T>::addEnd()
{
++endP;
} template<typename T>
int MyVector2<T>::PushBack(const T& _T)
{
int result=-1;
if(endP>=firstP && endP<CapicityP)
{
new (endP) T(_T);
++endP;
}
else
{
//MyVector2<T> temp=MyVector2(2*size());//最开始一直出错.debug才发现,犯了一个基础知识错误.
//这里建立的对象,离开作用域会调用西够函数.所以直接分配内存,而不是建立临时对象.免去西构问题.
T* TempfirstP=(T*)malloc(sizeof(T)*2*size());
T* TempendP=TempfirstP;
T* TempCapcityP=TempfirstP+(2*size()); cout<<"pushback malloc:"<<TempfirstP<<endl; T* s_iterator=this->firstP;
for(s_iterator;s_iterator!=(this->endP);++s_iterator)
{
new(TempendP) T(*s_iterator);//placement new .
++TempendP;
} del(); new (TempendP) T(_T);
++TempendP; firstP=TempfirstP;
endP=TempendP;
CapicityP=TempCapcityP;
}
return result;
} template<typename T>
T& MyVector2<T>::operator[](unsigned int _index)
{
if(_index>0)
{
return *(firstP+_index);
}
else
{
return *firstP;
}
} template<typename T>
void MyVector2<T>::del()
{
cout<<"del:"<<firstP<<endl;
free (firstP);
} #endif // MYVECTOR2_H_INCLUDED

  

main.cpp

#include <iostream>
#include <vector>
#include "myvector2.h" using namespace std; //为什么mb[0]=b2;是ok的.但是设计myvector中firstP=_T;确不行?
//为什么CapicityP=firstP+stepsize;防在函数体内每问题.而防入初始化却有问题? struct book
{
public:
book():name(""),bn(0),price(0){}
book(const string& _name,const int _bn,const double _price):name(_name),bn(_bn),price(_price){} book& operator=(const book& _lhs)
{
name=_lhs.name;
bn=_lhs.bn;
price=_lhs.price;
return *this;
}
book(const book& _rhs)
{
name=_rhs.name;
bn=_rhs.bn;
price=_rhs.price;
}
string bName()
{
return name;
}
void changeName(const string& _name)
{
name=_name;
}
~book(){}
private:
string name;
int bn;
double price;
}; void mainMyVector2();
void showInfo(const MyVector2<book>& books);
int main()
{
mainMyVector2();
//mainString();
//mainMyVector(); return 0;
} void mainMyVector2()
{
//实现功能基本:插入元素,pushback.
//引用构造,
//copy功能.
//按索引返回.
//删除索引位置元素. book b1=book("c++",01,2.5);
book b2=book("c",02,2);
book b3=book("c#",03,3.1); cout<<"*************push back***********"<<endl;
MyVector2<book> books1;//不需要book类有默认构造函数,因为使用的是c的malloc分配空间函数。而不是new建立数组。
books1.PushBack(b1);
books1.PushBack(b2);
books1.PushBack(b3);
showInfo(books1); for(int i=0;i!=40;++i)
{
books1.PushBack(b2);
}
showInfo(books1); cout<<"*************ref construct***********"<<endl;
MyVector2<book> books2=books1;//注意这里是构造初始化而不是copy。
showInfo(books2); cout<<"**************copy***********"<<endl;
MyVector2<book> books_capcity32;
showInfo(books_capcity32); books_capcity32=books1;
showInfo(books_capcity32); cout<<"*************index***********"<<endl;
cout<<"index 38:"<<books_capcity32[38].bName()<<". first:"<<books_capcity32[0].bName()<<endl; cout<<"*************earse***********"<<endl;
MyVector2<book> books3;
for(int i=0;i!=books3.size();++i)
{
cout<<books3[i].bName()<<endl;
}
showInfo(books3); books3.erace(0); books3.PushBack(b1);
books3.erace(0);
for(int i=0;i!=books3.size();++i)
{
cout<<books3[i].bName()<<endl;
}
showInfo(books3); books3.PushBack(b1);
books3.PushBack(b2);
books3.PushBack(b3); for(int i=0;i!=books3.size();++i)
{
cout<<books3[i].bName()<<endl;
}
books3.erace(1); for(int i=0;i!=books3.size();++i)
{
cout<<books3[i].bName()<<endl;
} showInfo(books3);
} void showInfo(const MyVector2<book>& books)
{
cout<<"size:"<<books.size()<<". capcity:"<<books.capcity()<<endl;
}

  

c++ vector 简单实现。的更多相关文章

  1. C++线性序列容器<vector>简单总结

    C++线性序列容器<vector>简单总结 vector是一个长度可变的数组,使用的时候无须声明上限,随着元素的增加,Vector的长度会自动增加:Vector类提供额外的方法来增加.删除 ...

  2. c++ 头文件 及 sort 和 vector简单介绍

    c++  sort :http://www.16kan.com/post/997260.html http://wenku.baidu.com/view/e064166daf1ffc4ffe47ac6 ...

  3. vector简单使用

    在刷ccf题的时候日常做完去网上查看别的同学怎么做的 发现有使用vector后三十几行代码就写出来的,虽然时间复杂度和我一样十几毫秒,but !我看中了它的代码量啊!多么的少啊! 所以百度了vecto ...

  4. C++STL vector简单使用练习1

    #include <iostream> #include <vector> #include <numeric> using namespace std; int ...

  5. Vector简单介绍

    /*枚举就是Vector特有的取出方式发现枚举和迭代器很像其实枚举和迭代是一样的因为枚举的名称以及方法的名称都过长了.所以被迭代器取代了枚举郁郁而终了. */ import java.util.*;c ...

  6. STL vector简单用法

    初涉c++,此为<算法笔记>中的内容,有待个人理解完善. vector vector翻译为向量,叫做"变长数组"更容易理解. 头文件:#include<vecto ...

  7. STL - 容器 - vector简单应用

    VectorTest.cpp #include <vector> #include <iostream> #include <string> #include &l ...

  8. c++vector简单实现

    const int DEFAULT_CAP = 3; template <typename T> class vector { // int capacity; T* _data; int ...

  9. vector简单常用用法

    Vector是什么? vector翻译为向量,从某种角度来说就是一个可以变长的数组,它会根据需要自动扩充数组的容量,除此之外其是一个STL中的模板类,其 还具有一些内部的方法. Vector的使用方法 ...

随机推荐

  1. Java常用jar包用途

    Java常用jar包用途: USAGE INDEX JAR NAME USAGE 1 ASM asm-2.2.3.jar ASM字节码库 2 ASM asm-commons-2.2.3.jar ASM ...

  2. 用PHP判断远程图片(文件)是否存在

    <?php function check_remote_file_exists($url) { $curl = curl_init($url); // 不取回数据 curl_setopt($cu ...

  3. JavaEE基础(二十六)/网络

    1.网络编程(网络编程概述) A:计算机网络 是指将地理位置不同的具有独立功能的多台计算机及其外部设备,通过通信线路连接起来,在网络操作系统,网络管理软件及网络通信协议的管理和协调下,实现资源共享和信 ...

  4. codeigniter中base_url和site_url

    首先在网站中使用如下的语句: site_url(‘manage/articleAdd’): 1 <?php echo site_url('manage/articleAdd');?> ba ...

  5. 通达OA 同步中控考勤机 增强版

    如果你用的是中控考勤机且考勤机能联网,那恭喜有福了! 最近发现考勤机提供web方式查询,经过调试可以用程序直接读取考勤机数据跨过考勤机软件及其access数据库,数据同步及时性.可靠性大幅提高. 通达 ...

  6. 使用epel源安装依赖包时报错

    [root@test_web1 ~]#  rpm -ivh http://dl.fedoraproject.org/pub/epel/6/x86_64/epel-release-6-8.noarch. ...

  7. 获取手机IMEI 号和 IP

    没什么可说的,直接上代码: public class PhoneStateCodeUtils { /** * 获取手机imei串号 */ public static String getImei(Co ...

  8. Dual Core CPU

    Dual Core CPU Time Limit: 15000MS Memory Limit: 131072K Total Submissions: 20935 Accepted: 9054 Case ...

  9. Unity脚本在层级面板中的执行顺序测试1

    第二篇测试循环时和动态创建时的调用顺序:LINK 测试版本Unity4.6.因为新版本对Transform的排序做了改变,所以不排除旧版本的测试结果不一样.测试时,使用Awake中添加Debug.lo ...

  10. C#中另类自定义公式计算 字符串转换为计算公式,并得出计算结果

    [csharp] view plain copy print? //方法一 利用DataTable中的Compute方法 例如:1*2-(4/1)+2*4=6 , , , ); DataTable d ...