• 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>中。




  • 相关阅读:
    [原]80386中断表
    [原]elf可执行连接文件格式
    [原]nasm语法
    VLAN基础配置及Access接口
    配置hybird接口
    配置Trunk接口
    [导入]Oracle常用技巧和脚本
    [导入]ORACLE 常用的SQL语法和数据对象
    [导入]Oracle 基本知识
    [导入]Oracle特殊包
  • 原文地址:https://www.cnblogs.com/averson/p/5096052.html
Copyright © 2020-2023  润新知