C++ Primer : 第十三章 : 动态内存管理类

/* StrVec.h */

#ifndef _STRVEC_H_
#define _STRVEC_H_

#include <memory>
#include <string>
#include <vector>
#include <utility>

class StrVec {

public:
	
	StrVec() : first(nullptr), last_end(nullptr), cap(nullptr){}
	StrVec(const StrVec&);
	StrVec& operator = (const StrVec&);
	~StrVec ();


	void push_back(std::string&);

	size_t size(){ return (last_end - first); }
	size_t capacity(){ return (cap - first);}

	std::string* begin() const { return first; }
	std::string* end() const { return last_end; }


private:

	static std::allocator<std::string> alloc; // 分配元素

	std::string* first;		 // first element pointer(begin())
	std::string* last_end;	 // last_end element pointer(end())
	std::string* cap;		 //	capacity pointer

	std::pair<std::string*, std::string*> alloc_n_copy (const std::string*, const std::string*);

	void chk_n_alloc (){
		if (size() == capacity())
			reallocate();
	}

	void free ();
	void reallocate ();

};

#endif // _STRVEC_H_


#include "StrVec.h"

StrVec::StrVec(const StrVec& s){

	auto newData =	alloc_n_copy(s.begin(), s.end());

	first		 =	newData.first;
	last_end	 =  cap = newData.second;

}

StrVec& StrVec::operator=(const StrVec& s){

	auto data = alloc_n_copy(s.begin(), s.end());
	free();
	first = data.first;
	last_end = cap = data.second;
	return *this;
}

StrVec::~StrVec(){
	free();
}

void StrVec::push_back(std::string& str){

	chk_n_alloc();
	alloc.construct(last_end++, str);
}

std::pair<std::string*, std::string*> StrVec::alloc_n_copy(const std::string* begin, const std::string* end){

	auto data = alloc.allocate(end - begin);
	return {data, uninitialized_copy(begin, end, data)};
}

void StrVec::free(){

	if (nullptr != first){

		for (auto p = last_end; p >= first;)
			alloc.destroy(--p);
		alloc.deallocate(first, cap - first);
	}

}

void StrVec::reallocate(){

	size_t newSize =  size() * 2;
		
	auto newdata   = alloc.allocate(newSize);

	auto dest  = newdata;
	auto fst   = first;

	// move the old elements
	for (size_t i = 0; i != size(); ++i)
		alloc.construct(dest++, std::move(*fst++));

	free();
	first		=	newdata;
	last_end	=	dest;
	cap			=	first + newSize;
}

当使用allcator重新分配内存时,我们应该移动原来的数据而不是拷贝,如果有大量的数据,拷贝会非常浪费时间和空间资源,因此我们用到了标准库函数std::move,它定义在有文件 <utility>中。




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值