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. 动态内存管理类的更多相关文章

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

    /* StrVec.h */ #ifndef _STRVEC_H_ #define _STRVEC_H_ #include <memory> #include <string> ...

  2. [C++ Primer] : 第13章: 拷贝控制

    拷贝, 赋值与销毁 当定义一个类时, 我们显示地或隐式地指定在此类型的对象拷贝, 移动, 赋值和销毁时做什么. 一个类通过定义5种特殊的成员函数来控制这些操作, 包括: 拷贝构造函数, 拷贝赋值运算符 ...

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

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

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

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

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

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

  6. uCGUI动态内存管理

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

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

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

  8. FreeRTOS 动态内存管理

    以下转载自安富莱电子: http://forum.armfly.com/forum.php 本章节为大家讲解 FreeRTOS 动态内存管理,动态内存管理是 FreeRTOS 非常重要的一项功能,前面 ...

  9. C++程序设计入门 引用和动态内存管理学习

    引用: 引用就是另一个变量的别名,通过引用所做的读写操作实际上是作用于原变量上. 由于引用是绑定在一个对象上的,所以定义引用的时候必须初始化. 函数参数:引用传递 1.引用可做函数参数,但调用时只需 ...

随机推荐

  1. MySQL邮件使用情况统计方法

    邮件使用情况统计方法如下: ) AS domain, COUNT(DISTINCT [column_name]) AS mail_count, COUNT([column_name]) AS mail ...

  2. CentOS下安装zookeeper并设置开机自启动

    转自: 一.安装zookeeper # cd /opt/ # mkdir zookeeper # cd zookeeper/ # tar -zxvf zookeeper-3.4.6.tar.gz # ...

  3. 将文本(lrc,txt)文件转换成UTF-8格式

    UTF-8是UNICODE的一种变长字符编码又称万国码,由Ken Thompson于1992年创建.现在已经标准化为RFC 3629.UTF-8用1到6个字节编码UNICODE字符.用在网页上可以同一 ...

  4. 自动升级CentOS Python至官方最新版

    #!/bin/bash # .检查当前系统Python版本 python_old_version=$(python -V >& | awk '{print $2}') echo &quo ...

  5. Android studio 自动导入(全部)包 import

    http://blog.csdn.net/buaaroid/article/details/44979629 1 Android studio 只有import单个包的快捷键:Alt+Enter.没有 ...

  6. Github安全整理(转载)

    刚好这两天对之前github上关注的一些比较有意思的项目进行了一下分类整理,在这里列出来分享给大家,希望能对大家寻找工具或者资源有所帮助. 大部分Repo是关于安全以及Python的,也有一些其他主题 ...

  7. luogu 1006 传纸条

    三/四维dp,将两次传递均看作从左上而来,在dp过程中注意防止越界/重合 f[i][j][k][l]直接枚举两轮的点,如下 #include<bits/stdc++.h> #define ...

  8. android app与服务器交互

    package mydemo.mycom.demo2.service; import org.apache.http.HttpResponse; import org.apache.http.Name ...

  9. sql 把多列内容合并

    这个语句不完整.应该是这样:stuff(select ',' + fieldname  from tablename for xml path('')),1,1,'') as ’别名‘这一整句的作用是 ...

  10. Linux - vim 编辑器

    gconf-editor # 配置编辑器 /etc/vimrc # 配置文件路径 vim +24 file # 打开文件定位到指定行 vim file1 file2 # 打开多个文件 vim -O2 ...