【C++ Primer 第13章】5. 动态内存管理类
StrVec类的设计
【题目描述】:我们将实现标准库vector类的一个简化版本,我们所做的一个简化是不使用模板,我们类只用于string,因此,它被命名为StrVec。
#include<iostream>
#include<string>
#include<memory>
using namespace std; class StrVec {
public:
StrVec(): elements(nullptr), first_free(nullptr), cap(nullptr) {}
StrVec(const StrVec &);
StrVec& operator=(const StrVec&);
~StrVec() { free(); }; StrVec(StrVec &&s) noexcept;
StrVec& opearator=(StrVec &&rhs) noexcept; void push_back (const string&);
size_t size() const { return first_free - elements; }
size_t capacity() const { return cap - elements; }
string *begin() const { return elements; }
string *end() const { return first_free; } private:
static allocator<string> alloc;
void chk_n_alloc() { if (size() == capacity()) reallocate(); }
pair<string*, string*> alloc_n_copy(const string*, const string *);
void free();
void reallocate();
string *elements; //指向数组首元素的指针
string *first_free; //指向数组第一个空闲元素的指针
string *cap; //指向数组尾后位置的指针
}; StrVec::StrVec(const StrVec &s)
{
auto newdata = alloc_n_copy(s.begin(), s.end());
elements = newdata.first;
first_free = cap = newdata.second;
} StrVec& StrVec::operator=(const StrVec &rhs)
{
auto data = alloc_n_copy(rhs.begin(), rhs.end());
free();
elements = data.first;
first_free = cap = newdata.second;
return *this;
} void StrVec::free()
{
if (elements)
{
for (auto p = first_free; p != elements; )
alloc.destroy(--p);
alloc.deallocate(elements, cap - elements);
}
} pair<string *, string *> StrVec::alloc_n_copy(const string *b, const string *e)
{
auto data = alloc.allocate(e - b);
return { data, uninitialized_copy(b, e, data) };
} void StrVec::push_back(const string& s)
{
chk_n_alloc();
alloc.construct(first_free++, s);
} void StrVec::reallocate()
{
auto newcapacity = size() ? * size() : ;
auto newdata = alloc.allocate(newcapacity);
auto dest = newdata;
auto elem = elements; //原对象的elements指针
for (size_t i = ; i != size(); ++i)
alloc.construct(dest++, std::move(*elem++));
free();
elements = newdata;
first_free = dest;
cap = elements + newcapacity;
} StrVec::StrVec(StrVec &&s) noexcept
: elements(s.elements), first_free(s.first_free), cap(s.cap)
{
s.elements = s.first_free = cap = nulllptr;
} StrVec& StrVec::StrVec(StrVec &&s) noexcept
{
if (this = &s)
{
free();
elemens = rhs.elements;
first_free = .frhsirst_free;
cap = rhs.cap;
rhs.elements = srhs.first_free = rhs.cap = nullptr;
}
return *this;
}
3.5节练习
• 编写标准库string类的简化版本,命名为string。
#include<iostream>
#include<memory>
#include<cstring>
#include<initializer_list>
using namespace std; class String {
friend String operator+(const String&, const String&);
friend String add(const String&, const String&);
friend ostream &operator<<(std::ostream&, const String&);
friend ostream &print(std::ostream&, const String&); public:
String():sz(), p(nullptr) {};
String(const char *cp): sz(strlen(cp)), p(p.allocate(sz)) { uninitialized_copy(cp, cp + sz, p)}
String(const String &s): sz(s.sz), p(a.allocate(sz)) { uninitialized_copy(s.p, s.p + sz, p)}
String(size_t n, char c): sz(n), p(a.allocate(n)) {uninitialized_fill_n(p, n, t)}
~String() noexcept { if (p) a.deallocate(p, sz); } String &operator=(const String &);
String &operator=(const char*);
String &operator=(char);
String &operator=(initializer_list<char>); const char *begin() { return p; }
const char *begin() const { return p; }
const char *end() { return p + sz; }
const char *end() const { return p + sz; }
size_t size() const { return sz; }
void swap(String &s); private:
static allocator<char> a;
size_t sz;
char *p;
}; /***********************************************************************************/
ostream &operator<<(ostream &os, const string &s)
{
return print(os, rhs);
} ostream &print(ostream &os, const string &s)
{
auto p = s.begin();
while(p != s.end())
os << *p++;
return os;
} string add(const string &lhs, const string &rhs)
{
string ret;
ret.sz = lhs.size() + rhs.size();
ret.p = a.allocate(ret.sz);
uninitialized_copy(lhs.begin(), lhs.end(),ret.p);
uninitialized_copy(rhs.begin(), rhs.end(), ret.p + lhs.sz);
return ret;
} string operator+(const string &lhs, const string &rhs)
{
return add(lhs, rhs);
}
/************************************************************************************/ String &String::operator=(const String &rhs)
{
auto newp = a.allocator(rhs.sz);
uninitlized_copy(rhs.p, rhs.p + rhs.ze, newp);
if (p)
a.deallocate(p, sz);
p = newp;
sz = rhs.sz;
return *this;
} String &String::operator=(const char *cp)
{
if(p)
a.deallocate(p, sz);
p = a.allocate(sz = strlen(cp));
uninitialzied_copy(cp, cp + sz, p);
return *this;
} String &String::operator=(char c)
{
if(p)
a.deallocate(p, sz);
p = a.allocate(sz = );
*p = c;
return *this;
} String& string::operator=(initializer_list<char> il)
{
if(p)
a.deallocate(p, sz);
p = a.llocate(il.size());
uninitialized_copy(il.begin(), il.end(), p);
return *this;
} /***************************************************************************************/ void string::swap(String &s)
{
auto tmp = p;
p = s.p;
s.p = tmp;
auto cnt = sz;
sz = s.sz;
s.sz = cnt;
} void swap(String &s1, String &s2)
{
s1.swap(s2); String make_plural(size_t ctr, const String &, const String &)
{
return (ctr != ) ? add(word, ending) : word;
}
【C++ Primer 第13章】5. 动态内存管理类的更多相关文章
- C++ Primer : 第十三章 : 动态内存管理类
/* StrVec.h */ #ifndef _STRVEC_H_ #define _STRVEC_H_ #include <memory> #include <string> ...
- [C++ Primer] : 第13章: 拷贝控制
拷贝, 赋值与销毁 当定义一个类时, 我们显示地或隐式地指定在此类型的对象拷贝, 移动, 赋值和销毁时做什么. 一个类通过定义5种特殊的成员函数来控制这些操作, 包括: 拷贝构造函数, 拷贝赋值运算符 ...
- (原创)动态内存管理练习 C++ std::vector<int> 模拟实现
今天看了primer C++的 “动态内存管理类”章节,里面的例子是模拟实现std::vector<std::string>的功能. 照抄之后发现编译不通过,有个库函数调用错误,就参考着自 ...
- C++动态内存管理与源码剖析
引言 在本篇文章中,我们主要剖析c++中的动态内存管理,包括malloc.new expression.operator new.array new和allocator内存分配方法以及对应的内存释放方 ...
- C++动态内存管理之shared_ptr、unique_ptr
C++中的动态内存管理是通过new和delete两个操作符来完成的.new操作符,为对象分配内存并调用对象所属类的构造函数,返回一个指向该对象的指针.delete调用时,销毁对象,并释放对象所在的内存 ...
- uCGUI动态内存管理
动态内存的堆区 /* 堆区共用体定义 */ typedef union { /* 可以以4字节来访问堆区,也可以以1个字节来访问 */ ]; /* required for proper aligne ...
- Keil C动态内存管理机制分析及改进(转)
源:Keil C动态内存管理机制分析及改进 Keil C是常用的嵌入式系统编程工具,它通过init_mempool.mallloe.free等函数,提供了动态存储管理等功能.本文通过对init_mem ...
- FreeRTOS 动态内存管理
以下转载自安富莱电子: http://forum.armfly.com/forum.php 本章节为大家讲解 FreeRTOS 动态内存管理,动态内存管理是 FreeRTOS 非常重要的一项功能,前面 ...
- C++程序设计入门 引用和动态内存管理学习
引用: 引用就是另一个变量的别名,通过引用所做的读写操作实际上是作用于原变量上. 由于引用是绑定在一个对象上的,所以定义引用的时候必须初始化. 函数参数:引用传递 1.引用可做函数参数,但调用时只需 ...
随机推荐
- vue项目 打包部署上线
1. npm run dev:本地开发的时候做调试用的. 2. npm run build:打包部署上线,生成一个 dist 文件夹. 注意:用 npm run build 时,常遇到因引用路径不对导 ...
- MVC中常用的跳转方法
MVC中常用的跳转方法 这里总结了几种MVC中的跳转方式,主要汇总了前端页面跳转,后台的跳转,和过滤器中的跳转方式. 1.在前端页面的跳转方式 <!--属性形式---> <a hre ...
- 骨骼动画的原理及在Unity中的使用
制作骨骼动画 我们看看这几步操作后,我们得到了那些数据: 1.每个皮肤顶点的初始世界坐标. 2.每个骨骼关节顶点的初始世界坐标. 3.每个顶点被骨骼顶点的影响信息. 4.骨骼如何移动. 骨骼动画原理 ...
- python 之禅 import this
dongweiming的博客 前言 我这个博客一直都是一些技术分享,show code的地方,我从来没有写过个人生活或者情感杂谈,当然我也从来没有谈论过我对什么东西的喜恶. 很多人喜欢喷XX语言,喜欢 ...
- indexOf与includes的比较
indexOf和includes都代表检测数组或字符串中是否包含某一个元素 其中indexOf返回的是数值类型,而includes返回的是布尔类型 var ary = [,,]; console.lo ...
- Spring 学习04
一.上节内容回顾 1 基于aspectj的注解aop操作 2 spring的jdbcTemplate操作 (1)实现crud操作 - 添加.修改.删除update方法 - 查询 -- 查询某个值 qu ...
- 使用java.util.LinkedList模拟实现内存页面置换算法--LRU算法
一,LRU算法介绍 LRU是内存分配中“离散分配方式”之分页存储管理方式中用到的一个算法.每个进程都有自己的页表,进程只将自己的一部分页面加载到内存的物理块中,当进程在运行过程中,发现某页面不在物理内 ...
- C# 窗体最大化(自适应任务栏位置)
this.FormBorderStyle = FormBorderStyle.None; this.Location=Screen.PrimaryScreen.WorkingArea.Location ...
- Nginx 内核优化
内核参数的优化示例: /etc/sysctl.conf net.ipv4.tcp_max_tw_buckets = // timewait的数量,默认是180000. net.ipv4.ip_loca ...
- luogu P2516 [HAOI2010]最长公共子序列
传送门 首先那个\(O(n^2)\)的dp都会吧,不会自己找博客或者问别人,或是去做模板题(误) 对以下内容不理解的,强势推荐flash的博客 我们除了原来记录最长上升子序列的\(f_{i,j}\), ...