/* 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>中。

C++ Primer : 第十三章 : 动态内存管理类的更多相关文章

  1. [C++ Primer] : 第12章: 动态内存

    动态内存与只能指针 静态内存用来保存局部static对象, 类static数据成员以及定义在任何函数之外的变量. 栈内存用来保存定义在函数内的非static对象. 分配在静态或栈内存中的对象由编译器自 ...

  2. 【C++ Primer 第13章】5. 动态内存管理类

    StrVec类的设计 [题目描述]:我们将实现标准库vector类的一个简化版本,我们所做的一个简化是不使用模板,我们类只用于string,因此,它被命名为StrVec. #include<io ...

  3. C++ Primer : 第十二章 : 动态内存之shared_ptr类实例:StrBlob类

    StrBlob是一个管理string的类,借助标准库容器vector,以及动态内存管理类shared_ptr,我们将vector保存在动态内存里,这样就能在多个对象之间共享内存. 定义StrBlob类 ...

  4. (原创)动态内存管理练习 C++ std::vector<int> 模拟实现

    今天看了primer C++的 “动态内存管理类”章节,里面的例子是模拟实现std::vector<std::string>的功能. 照抄之后发现编译不通过,有个库函数调用错误,就参考着自 ...

  5. C++ Primer : 第十三章 : 拷贝控制之对象移动

    右值引用 所谓的右值引用就是必须将引用绑定到右值的引用,我们通过&&来绑定到右值而不是&, 右值引用只能绑定到即将销毁的对象.右值引用也是引用,因此右值引用也只不过是对象的别名 ...

  6. C++动态内存管理与源码剖析

    引言 在本篇文章中,我们主要剖析c++中的动态内存管理,包括malloc.new expression.operator new.array new和allocator内存分配方法以及对应的内存释放方 ...

  7. C++动态内存管理之shared_ptr、unique_ptr

    C++中的动态内存管理是通过new和delete两个操作符来完成的.new操作符,为对象分配内存并调用对象所属类的构造函数,返回一个指向该对象的指针.delete调用时,销毁对象,并释放对象所在的内存 ...

  8. uCGUI动态内存管理

    动态内存的堆区 /* 堆区共用体定义 */ typedef union { /* 可以以4字节来访问堆区,也可以以1个字节来访问 */ ]; /* required for proper aligne ...

  9. Keil C动态内存管理机制分析及改进(转)

    源:Keil C动态内存管理机制分析及改进 Keil C是常用的嵌入式系统编程工具,它通过init_mempool.mallloe.free等函数,提供了动态存储管理等功能.本文通过对init_mem ...

随机推荐

  1. DSO、CUBE区别(覆盖、合计)

    声明:原创作品,转载时请注明文章来自SAP师太技术博客( 博/客/园www.cnblogs.com):www.cnblogs.com/jiangzhengjun,并以超链接形式标明文章原始出处,否则将 ...

  2. 从ASP了解Http Buffer

    he Buffer property specifies whether to buffer the output or not. When the output is buffered, the s ...

  3. (六)文件操作的主要接口API

    1.什么是操作系统API (1)API是一些函数,这些函数是由linux系统提供支持的,由应用层程序来使用. (2)应用层程序通过调用API来调用操作系统中的各种功能,来干活. (3)学习一个操作系统 ...

  4. zabbix3.0.4 部署之四 (LNAP > PHP安装)

    1.安装依赖 安装epel-release源 安装 libiconv-1.14.tar.gz (这个还有个devl包)  libmcrypt-2.5.8.tar.gz   mhash-0.9.9.9. ...

  5. HTML 文本格式化<b><big><em><i><small><strong><sub><sup><ins><del>

    <b> 标签-粗体 定义和用法: <b>标签规定粗体文本. 提示和注释 注释:根据 HTML5 规范,在没有其他合适标签更合适时,才应该把 <b> 标签作为最后的选 ...

  6. Windows—JDK安装与环境变量配置

    本文介绍JDK的安装与环境变量配置. 工具/原料 JDK1.8.0_65 WIN7 32bit jdk-8u65-windows-i586.exe 方法/步骤  安装JDK 选择安装目录 安装过程中会 ...

  7. NET中的规范标准注释(一) -- XML注释标签讲解

    一.摘要 .Net允许开发人员在源代码中插入XML注释,这在多人协作开发的时候显得特别有用. C#解析器可以把代码文件中的这些XML标记提取出来,并作进一步的处理为外部文档. 这篇文章将展示如何使用这 ...

  8. Oracle权限管理详解

    Oracle权限管理详解 转载--CzmMiao的博客生活 Oracle 权限 权限允许用户访问属于其它用户的对象或执行程序,ORACLE系统提供三种权限:Object 对象级.System 系统级. ...

  9. PHP 缓存扩展opcache

    opcache (全程 zend opcache): 从php5.5开始,默认提供的php脚本缓存扩展,编译php5.5时加上参数--enable-opcache就可以编译opcache了,只是要启用 ...

  10. 由ArrayList构造函数源码引出的问题

    ArrayList应该用得很多了.最近看了看其源码,发现有很多细节,如果要我们自己来实现,估计会考虑不到.当然,这些细节跟jdk本身一些实现的bug有关,如果不去深挖,定然是不能发现.本文从Array ...