Accelerated C++ —— 简易版std::vector类的实现

#include <memory>
#include <iostream>
#include <algorithm>
namespace Ming {
	template<class T> class vec
	{
	public:
		typedef T* iterator;
		typedef const T* const_iterator;
		//typedef typename std::vector<T>::size_type size_type;
		typedef size_t size_type;
		typedef T value_type;
		typedef T& reference;
		typedef const T& const_reference;

		//-------------------------------------构造函数
		//--重写默认构造函数
		vec() {
			create();
		}
		//--带参构造函数
		//对于只带有一个参数的构造函数,用户只能这样vec<int> a(100);来调用构造函数初始化,不能vec<int> a = 100;
		//即explicit 消除了隐式转换
		explicit  vec(size_type n, const T& val = T()) {
			create(n, val);
		}
		//--复制构造函数
		vec(const vec &v) {
			std::cout << "复制啦" << std::endl;
			create(v.cbegin(), v.cend());
		}
		//--析构函数
		~vec() {
			uncreate();
		}

		//--------------------------------------重载操作符号
		/*声明赋值操作符*/
		vec& operator=(const vec&);//相当于vec<T>& vec<T>::operator=(const vec&);
		/* 返回引用,1、方面调用a[i]=nums;来修改值2、避免经常复制,效率高*/
		T& operator[](size_type i) {
			return data[i];
		}
		const T& operator[](size_type i)const
		{
			return data[i];
		}

		//---------------------------------------迭代器(对系统指针进行改写)
		iterator begin() { return data; }
		iterator end() { return avail; }
		const_iterator cbegin() const { return data; }
		const_iterator cend()const { return avail; }

		//---------------------------------------成员函数
		/* 获取动态数组大小*/
		size_type size()const { return avail - data; }
		void push_back(const T& val)
		{
			if (avail == limit)//空间不足,重新申请空间
				grow();
			unchecked_append(val);//插入新元素
		}

	private:
		iterator data;
		iterator avail;
		iterator limit;

		std::allocator<T> alloc;

		void create();
		void create(size_type, const_reference);
		void create(const_iterator, const_iterator);

		void uncreate();

		void grow();
		void unchecked_append(const_reference);
	};

	/*赋值操作符实现*/
	/*
	 * !!当用=为一个变量提供一个初始值时,调用的是复制构造函数(copy constructor):直接进行赋值
	 * !!当用=为一个变量进行赋值时,调用的是operator=函数:先删除先前的值,在进行赋值
	 */
	template <class T>
	vec<T>& vec<T>::operator=(const vec<T> &rhs)
	{
		std::cout << "赋值啦" << std::endl;
		//****检查是否自我赋值【若不判断,则会导致uncreate()销毁this本身的内容,若rhs=this,则rhs也被销毁了】
		if (&rhs != this)//this类型是vec*,指向成员函数operator=操作的对象的指针
						//this绑定在左操作数上
		{
			uncreate();//释放左值this数组内容
			create(rhs.cbegin(), rhs.cend());//从右值复制给左值
		}
		return *this;
	}

	template <typename  T>
	void vec<T>::create()
	{
		data = avail = limit = nullptr;
	}
	template <typename T>
	void vec<T>::create(size_type n, const_reference val)
	{
		data = alloc.allocate(n);//分配n个能够存放T的空间,并返回指向这块空间的首元素的指针
		limit = avail = data + n;//均指向末尾
		std::uninitialized_fill(data, limit, val);//初始化内存空间
	}
	template <typename T>
	void vec<T>::create(const_iterator i, const_iterator j)
	{
		data = alloc.allocate(j - i);
		limit = avail = std::uninitialized_copy(i, j, data);//初始化内存空间//返回最后一个复制赋值的下一个位置【按道理来讲应该是指向空】
	}

	template <typename T>
	void vec<T>::uncreate()
	{
		if (data != nullptr)
		{
			iterator it = avail;
			while (it != data)
				alloc.destroy(--it);//先自减,再用alloc销毁it指向的内存块

			alloc.deallocate(data, limit - data);//**deallocate()只能传入非空指针以及长度!!!
		}
		data = limit = avail = nullptr;
	}

	template <typename T>
	void vec<T>::grow()
	{
		//两个指针相减的结果的类型为ptrdiff_t,它是一种有符号整数类型。
		//减法运算的值为两个指针在内存中的距离(以数组元素的长度为单位,而非字节),
		//因为减法运算的结果将除以数组元素类型的长度。所以该结果与数组中存储的元素的类型无关。
		size_type new_size = std::max(2 * (limit - data), static_cast<ptrdiff_t>(1));

		//申请更大(2倍)的内存空间
		//将原先内容复制到新的内存空间
		iterator new_data = alloc.allocate(new_size);
		iterator new_avail = std::uninitialized_copy(data, avail, new_data);

		//释放原先旧的内存空间
		uncreate();

		data = new_data;
		avail = new_avail;
		limit = new_data + new_size;
	}

	template <typename T>
	void vec<T>::unchecked_append(const_reference val)
	{
		alloc.construct(avail, val);//将val值复制到avail所指的内存块中
		++avail;
	}
}
using namespace Ming;
int main()
{
	vec<int> temp(2, 1);
	temp.push_back(2);
	temp.push_back(3);
	temp.push_back(4);
	for (auto i = temp.begin(); i != temp.end(); ++i)
		std::cout << *i << std::endl;

	vec<int> temp1 = temp;	//复制构造函数
	temp = temp1;		//赋值构造函数

	vec<int> temp2(10);
	//vec<int> temp3 = 10;//只有一个参数的构造函数,有explicit则报错,无explicit则对
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Accelerated C++源代码 本书全面介绍了C++语言。作为一本入门书(Primer),它以教程的形式对C++语言进行清晰的讲解,并辅以丰富的示例和各种学习辅助手段。与大多数入门教程不同,本书对C++语言本身进行了详尽的描述,并特别着重介绍了目前通行的、行之有效的程序设计技巧。   无数程序员曾使用本书的前几个版本学习C++,在此期间C++也逐渐发展成熟。这些年来,C++语言的发展方向以及C++程序员的关注点,已经从以往注重运行时的效率,转到千方百计地提高程序员的编程效率上。随着标准库的广泛可用,我们现在能够比以往任何时候更高效地学习和使用C++。本书这一版本充分体现了这一点。第4版的改动为了体现现代C++编程风格,我们重新组织并重写了本书。书中不再强调低层编程技术,而把中心转向标准库的使用。书中很早就开始介绍标准库,示例也已经重新改写,充分利用了标准库设施。我们也对语言主题叙述的先后次序进行了重新编排,使讲解更加流畅。除重新组织内容外,为了便于读者理解,我们还增加了几个新的环节。每一章都新增了“小结”和“术语”,概括本章要点。读者可以利用这些部分进行自我检查;如果发现还有不理解的概念,可以重新学习该章中的相关部分。书中还加入了下述几种学习辅助手段:重要术语用黑体表示,我们认为读者已经熟悉的重要术语则用楷体表示。这些术语都会出现在章后的“术语”部分。书中用特殊版式突出标注的文字,是为了向读者提醒语言的重要特征,警示常见的错误,标明良好的编程实践,列出通用的使用技巧。希望这些标注可以帮助读者更快地消化重要概念,避免犯常见错误。为了更易于理解各种特征或概念间的关系,书中大量使用了前后交叉引用。.. 对于某些重要概念和C++新手最头疼的问题,我们进行了额外的讨论和解释。这部分也以特殊版式标出。学习任何程序设计语言都需要编写程序。因此,本书提供了大量的示例。所有示例的源代码可从下列网址获得: http://www.awprofessional.com/cpp_primer 万变不离其宗,本书保持了前几版的特色,仍然是一部全面介绍C++的教程。我们的目标是提供一本清晰、全面、准确的指南性读物。我们通过讲解一系列示例来教授C++语言,示例除了解释语言特征外,还展示了如何善用这门语言。虽然读者不需要事先学过C语言(C++最初的基础)的知识,但我们假定读者已经掌握了一种现代结构化语言。本书结构本书介绍了C++国际标准,既涵盖语言的特征,又讲述了也是标准组成部分的丰富标准库。C++的强大很大程度上来自它支持抽象程序设计。要学会用C++高效地编程,只是掌握句法和语义是远远不够的。我们的重点,在于教会读者怎样利用C++的特性,快速地写出安全的而且性能可与C语言低层程序相媲美的程序。 C++是一种大型的编程语言,这可能会吓倒一些新手。现代C++可以看成由以下三部分组成: l 低级语言,多半继承自C。 l 更高级的语言特征,用户可以借此定义自己的数据型,组织大规模的程序和系统。 l 标准库,使用上述高级特征提供一整套有用的数据结构和算法。多数C++教材按照下面的顺序展开:先讲低级细节,再介绍更高级的语言特征;在讲完整个语言后才开始解释标准库。结果往往使读者纠缠于低级的程序设计问题和复杂型定义的编写等细节,而不能真正领会抽象编程的力量。就更不用说学到足够的知识去创建自己的抽象了。本版中我们独辟蹊径。一开始就讲述语言的基础知识和标准库,这样读者就可以写出比较大的有实际意义的程序来。透彻阐释了使用标准库(并且用标准库编写了各种抽象程序)的基础知识之后,我们才进入下一步,学习用C++的其他高级特征,来编写自己的抽象。第一和第二部分讨论语言的基础知识和标准库设施。其重点在于学会如何编写C++程序,如何使用标准库提供的抽象设施。大部分C++程序员需要了解本书这两部分的内容。除了讲解基础知识以外,这两部分还有另外一个重要的意图。标准库设施本身是用C++编写的抽象数据型,定义标准库所使用的是任何C++程序员都能使用的构造的语言特征。我们教授C++的经验说明,一开始就使用设计良好的抽象型,读者会更容易理解如何建立自己的型。第三到第五部分着重讨论如何编写自己的型。第三部分介绍C++的核心,即对的支持。机制提供了编写自定义抽象的基础。也是第四部分中所讨论的面向对象编程和泛型编程的基础。全书正文的最后是第五部分,我们在这一部分讨论了一些高级特征,它们在构建大型复杂系统时最为常用。致谢与前几版一样,我们要感谢Bjarne Stroustrup,他不知疲倦地从事着C++方面的工作,他与我们的深厚友情由来已久。我们还要感谢Alex Stepanov,正是他最初凭借敏锐的洞察力创造了容器和算法的概念,这些概念最终形成了标准库的核心。此外,我们要感谢C++

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值