【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.引用可做函数参数,但调用时只需 ...
随机推荐
- socket技术详解(看清socket编程)
socket编程是网络常用的编程,我们通过在网络中创建socket关键字来实现网络间的通信,通过收集大量的资料,通过这一章节,充分的了解socket编程,文章用引用了大量大神的分析,加上自己的理解,做 ...
- JAVA记录-添加错误页面友好提示
1.web.xml加入以下配置 <error-page> <error-code>404</error-code> <location>/WEB-INF ...
- Nginx 学习笔记(五)nginx-vod-module 模块
nginx-vod-module 一.编译 ./configure \ --user=www \ --group=www \ --prefix=/usr/local/openresty \ --wit ...
- JSON与对象的相互转换
json是一种轻量级的数据格式,(本质为字符串) 低版本可以使用json2.js插件来解决.下载地址:https://github.com/douglascrockford/JSON-js JSON语 ...
- Emacs org-mode导出html出错
不知道为什么,当org文件中含有#+TITLE:xxx时,导出会报类似下面的错误: Wrong type argument: listp, #("xxx" 0 3 (:parent ...
- 基于802.11Fuzz技术的研究
转自安全客 关于无线的Fuzz最开始接触了解时,国内基本毛线都搜不到.经过几个月的资料搜集和学习,将大约全网的fuzz资料整理翻译分析并读懂写下,就为填补国内空白,也希望无线爱好者能多多交流. 在各个 ...
- android 获取图库中展示到界面中
layout: <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns: ...
- Qt之QEvent(所有事件的翻译)
QEvent 类是所有事件类的基类,事件对象包含事件参数. Qt 的主事件循环(QCoreApplication::exec())从事件队列中获取本地窗口系统事件,将它们转化为 QEvents,然后将 ...
- JavaScript之HTML5 data-* 自定义属性[HTML5标准 node.dataset.attributeName]
在HTML5中添加了data-*的方式来自定义属性,所谓data-*实际上上就是data-前缀加上自定义的属性名,使用这样的结构可以进行数据存放. 使用data-*可以解决自定义属性混乱无管理的现状. ...
- 免费的馅饼 HYSBZ - 2131 (树状数组维护二维偏序)
题目链接:https://cn.vjudge.net/problem/HYSBZ-2131 题目大意:中文题目 具体思路:对于任意的两个位置,posA和posB,我们可以如下推导. |posA-pos ...