C++primer(动态内存管理类)

一.每个代码几乎都有详细注释(后附测试结果)

#include <iostream>
#include <string>
#include <vector>
#include <queue>
#include <stdexcept>
#include <cmath>
#include <cassert>
#include <fstream>
#include <sstream>
#include <deque>
#include <list>
#include <algorithm>
#include <numeric>
#include <functional>
#include <map>
#include <memory>
#include <cstring>
#include <set>
using namespace std;
class strVec
{
public:
	strVec() : elements(nullptr), frist_free(nullptr), cap(nullptr) {} //默认构造
	strVec(const strVec &);											   //拷贝构造
	strVec &operator=(const strVec &);								   //拷贝赋值运算符
	~strVec();														   //析构函数
	void push_back(const string &);									   // push_back 函数
	size_t size() const { return frist_free - elements; }
	size_t capcity() const { return cap - elements; }
	string *begin() const { return elements; }
	string *end() const { return frist_free; }
	void reserve(size_t &);
	void resize(size_t &);

private:
	static allocator<string> alloc;
	pair<string *, string *> alloc_n_copy(const string *, const string *);
	void chk_n_alloc() //如果内存空间不够,分配内存空间
	{
		if (size() == capcity()) //如果元素数量==容器容量
			reallocate();		 //重新分配内存空间
	}

	void free();		// destroy掉元素然后释放内存空间
	void reallocate();	//重新分配内存空间
	string *elements;	//指向分配的内存中的首位置
	string *frist_free; //指向分配的内存中第一个空闲位置(类似end())
	string *cap;		//指向分配的内存中最后一个空闲位置的后一个位置
};

allocator<string> strVec::alloc; //分配元素的
void strVec::push_back(const string &s)
{
	chk_n_alloc();
	alloc.construct(frist_free++, s); // first_free先被插入后递增,待s插入后依然指向第一个空闲空间
}

pair<string *, string *>
strVec::alloc_n_copy(const string *a, const string *b) //拷贝构造,拷贝赋值时会用到,
{
	auto data = alloc.allocate(b - a);			   //分配与给定范围一样大的内存空间,用data来暂时接收(data未初始化)
	return {data, uninitialized_copy(a, b, data)}; //返回一个pair对组,将(a,b)范围的元素拷贝至未初始化的内存空间里
}

void strVec::free() //销毁内容 ,然后释放分配的内存空间
{
	if (elements) //判断内存空间元素是否为空
	{
		for (auto i = frist_free; i != elements;) //逆序循环遍历元素
		{
			alloc.destroy(--i); //依次销毁元素
		}
		alloc.deallocate(elements, cap - elements); //释放分配的内存空间(析构函数用的上)
	}
}

strVec::strVec(const strVec &s1) //定义拷贝构造函数
{
	auto newdata = alloc_n_copy(s1.begin(), s1.end()); //分配内存,将s1里的所有元素拷贝到新分配的内存空间
	free();											   //销毁原有内存空间
	elements = newdata.first;						   //将newdata的元素 “从首元素开始依次存放” 当前内存空间中
	frist_free = cap = newdata.second;				   // newdata.second返回指向最后一个构造元素之后的位置
}

strVec::~strVec() //定义析构函数
{
	free(); //直接调用free()先销毁所有元素在释放分配的所有内存
}

strVec &strVec::operator=(const strVec &s)
{
	auto newdata = alloc_n_copy(s.begin(), s.end()); //分配内存,将s1里的所有元素拷贝到新分配的内存空间
	free();											 //销毁原有内存空间
	elements = newdata.first;						 //将newdata的元素 “从首元素开始依次存放” 当前内存空间中
	frist_free = cap = newdata.second;				 // newdata.second返回指向最后一个构造元素之后的位置
	return *this;									 //返回调用者本身
}
void strVec::reallocate()
{
	if (size() == capcity())
	{
		auto newcapcity=size() ? 2 * size() : 1;
		auto newdata = alloc.allocate(newcapcity); //分配两倍size()大小的内存空间
		auto dest = newdata;									//指向新空间的下一个空闲位置
		auto elem = elements;									//指向当前旧空间第一个元素
		for (decltype(size()) i = 0; i < size(); ++i)
		{
			alloc.construct(dest++, move(*elem++)); //将接引用的elem递增依次加入到新分配的数组中
		}
		free();						 //移动完成后释放原有数组内存空间
		elements = newdata;			 //赋予首地址,也就是指向新空间第一个元素
		frist_free = dest;			 // dest经过一系列递增后指向新空间的第一个空闲元素;
		cap = newcapcity+ elements; //新空间容量
	}
}
void strVec::reserve(size_t &s)
{
	if (s <= size()) //如果新空间<=当前存在元素的空间
	{
		return; //直接返回
	}
	else if (s > size()) //如果新空间大于当前存在有元素的空间
	{
		auto newdata = alloc.allocate(s); //分配两倍size()大小的内存空间
		auto dest = newdata;			  //指向新空间的下一个空闲位置
		auto elem = elements;			  //指向当前旧空间第一个元素
		for (decltype(size()) i = 0; i < size(); ++i)
		{
			alloc.construct(dest++, move(*elem++)); //将接引用的elem递增依次加入到新分配的数组中
		}
		free();				//移动完成后释放原有数组内存空间
		elements = newdata; //赋予首地址,也就是指向新空间第一个元素
		frist_free = dest;	// dest经过一系列递增后指向新空间的第一个空闲元素;
		cap = s + elements; //新空间容量
	}
}
void strVec::resize(size_t &s) //改变初始化的元素数量
{
	if (s > size())		//如果s>size()需要将s大小范围的内存空间全都初始化
	{
		auto newfrist_free = frist_free;
		for (size_t i = size(); i < s; ++i)
			alloc.construct(newfrist_free++, " "); //将多出来的几个内存空间用"  "初始化
		frist_free = newfrist_free;				//更新新的空闲空间
		return;
	}
	if (s > capcity())		//如果s的值大于capcity那么需要重新分配空间,并且要将所有元素都初始化
	{
		auto newdata = alloc.allocate(s); //分配s大小的内存空间
		auto dest = newdata;			  //指向新空间的下一个空闲位置
		auto elem = elements;			  //指向当前旧空间第一个元素
		auto oldsize = size();			  // b保存旧空间元素大小
		for (decltype(size()) i = 0; i < size(); ++i)
		{
			alloc.construct(dest++, move(*elem++)); //将解引用的elem递增依次加入到新分配的数组中
		}

		free();						 //移动完成后释放原有数组内存空间
		elements = newdata;			 //赋予首地址,也就是指向新空间第一个元素
		frist_free = dest;			 // dest经过一系列递增后指向新空间的第一个空闲元素;
		cap = 2 * size() + elements; //新空间容量

		auto newfrist_free = frist_free;	
		for (size_t i = oldsize; i < s; ++i)
			alloc.construct(newfrist_free++, " "); //将剩下的没有元素的内存空间用"  "初始化
		frist_free = newfrist_free;				//更新新的空闲空间
		return;
	}
	if (s < size())
	{
		auto newfrist_free = frist_free;
		for (size_t i = 0; i < size() - s; ++i)
			alloc.destroy(--newfrist_free);
		frist_free = newfrist_free;
		return;
	}
	if(s==size())
	return;
}
int main()
{
	strVec s;
	string s1="abc";
	s.push_back(s1);//添加第一个元素
	string s2="def";
	s.push_back(s2);//添加第二个元素
	cout<<*(s.begin())<<endl;//输出第一个元素
	cout<<s.size()<<endl;//输出内存中有多少元素
	size_t a=1;
	s.resize(a);	//resize<size()情况
	cout<<s.size()<<endl;//输出内存中元素数量
	size_t b=10;
	s.resize(b);	//resize>size()情况
	cout<<s.size()<<endl;//输出内存中元素数量
	size_t c=20;
	s.reserve(c);	
	cout<<s.capcity()<<endl;//输出
	return 0;
}

 二.测试结果

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小农农

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值