String类的写时拷贝
#include<iostream>
using namespace std;
class String;
ostream& operator<<(ostream &out, const String&s);
//引用计数器类
class String_rep
{
friend class String;
friend ostream& operator<<(ostream &out, const String&s);
public:
String_rep(const char *str )
:use_count(0)
{
if (str == NULL)
{
data = new char[1];
data[0] = '\0';
}
else
{
data = new char[strlen(str) + 1];
strcpy(data, str);
}
}
String_rep(const String_rep &rep) :use_count(0)
{
data = new char[strlen(rep.data) + 1];
strcpy(data, rep.data);
}
String_rep& operator=(const String_rep &rep)
{
if (this != &rep)
{
delete[]data;
data = new char[strlen(rep.data) + 1];
strcpy(data, rep.data);
}
return *this;
}
~String_rep()
{
delete[]data;
data = NULL;
}
public:
void increase()
{
++use_count;
}
void decrease()
{
if (use_count == 0)
{
delete this; //自杀行为 释放this所指的空间,在释放之前调动这个类的析构函数
}
}
private:
char *data;
int use_count;
};
////////////////////////////////////////////////////////////////////////////////////////
class String
{
friend ostream& operator<<(ostream &out, const String&s);
public:
String(const char* str = " ")
{
rep = new String_rep(str);
rep->increase();
}
String(const String &s)
{
rep = s.rep; //浅拷贝
rep->increase();
}
String& operator=(const String &s)
{
if (this != &s)
{
rep->decrease(); //模拟delete
rep = s.rep; //模拟new
rep->increase(); //模拟strcpy
/*rep = s.rep; //这会更改引用计数器指针 ,造成s内存泄漏
rep->increase();*/
}
return *this;
}
~String()
{
rep->decrease();
}
public:
void to_upper()
{
if (rep->use_count > 1)
{
String_rep* new_rep = new String_rep(rep->data);
rep->decrease();
rep = new_rep;
rep->increase();
}
char* ch = rep->data;
while (*ch != '\0')
{
*ch -= 32;
++ch;
}
}
private:
String_rep *rep; //引用计数器
};
ostream& operator<<(ostream &out, const String&s)
{
out << s.rep->data;
return out;
}
void main()
{
String s1("hello");
String s2(s1);
String s3;
s3 = s2;
cout << "s1=" << s1 << endl;
cout << "s2=" << s2 << endl;
cout << "s3=" << s3 << endl;
s2.to_upper();
cout << "-----------------------------------------------" << endl;
cout << "s1=" << s1 << endl;
cout << "s2=" << s2 << endl;
cout << "s3=" << s3 << endl;
}
String类的写时拷贝的更多相关文章
- String类的实现(4)写时拷贝浅析
由于释放内存空间,开辟内存空间时花费时间,因此,在我们在不需要写,只是读的时候就可以不用新开辟内存空间,就用浅拷贝的方式创建对象,当我们需要写的时候才去新开辟内存空间.这种方法就是写时拷贝.这也是一种 ...
- 标准C++类std::string的内存共享和Copy-On-Write(写时拷贝)
标准C++类std::string的内存共享,值得体会: 详见大牛:https://www.douban.com/group/topic/19621165/ 顾名思义,内存共享,就是两个乃至更多的对象 ...
- String 类的实现(2)引用计数与写时拷贝
1.引用计数 我们知道在C++中动态开辟空间时是用字符new和delete的.其中使用new test[N]方式开辟空间时实际上是开辟了(N*sizeof(test)+4)字节的空间.如图示其中保存N ...
- String写时拷贝实现
头文件部分 1 /* 版权信息:狼 文件名称:String.h 文件标识: 摘 要:对于上版本简易的String进行优化跟进. 改进 1.(将小块内存问题与大块分别对待)小内存块每个对象都有,当内存需 ...
- 计算机程序的思维逻辑 (73) - 并发容器 - 写时拷贝的List和Set
本节以及接下来的几节,我们探讨Java并发包中的容器类.本节先介绍两个简单的类CopyOnWriteArrayList和CopyOnWriteArraySet,讨论它们的用法和实现原理.它们的用法比较 ...
- 并发容器之写时拷贝的 List 和 Set
对于一个对象来说,我们为了保证它的并发性,通常会选择使用声明式加锁方式交由我们的 Java 虚拟机来完成自动的加锁和释放锁的操作,例如我们的 synchronized.也会选择使用显式锁机制来主动的控 ...
- Java编程的逻辑 (73) - 并发容器 - 写时拷贝的List和Set
本系列文章经补充和完善,已修订整理成书<Java编程的逻辑>,由机械工业出版社华章分社出版,于2018年1月上市热销,读者好评如潮!各大网店和书店有售,欢迎购买,京东自营链接:http: ...
- 写时拷贝(Copy On Write)方案详解
本文旨在通过对 写时拷贝 的四个方案(Copy On Write)分析,让大家明白写时拷贝的实现及原理. 关于浅拷贝与深拷贝,我在之前的博客中已经阐述过了 浅拷贝容易出现指针悬挂的问题,深拷贝效率低 ...
- rust漫游 - 写时拷贝 Cow<'_, B>
rust漫游 - 写时拷贝 Cow<'_, B> Cow 是一个写时复制功能的智能指针,在数据需要修改或者所有权发生变化时使用,多用于读多写少的场景. pub enum Cow<'a ...
随机推荐
- Jdbc入门
JDBC入门 l 导jar包:驱动! l 加载驱动类:Class.forName(“类名”); l 给出url.username.password,其中url背下来! l 使用DriverMa ...
- Object Pascal 运算符
Object Pascal 的运算符 运算符是程序代码中对各种类型的数据进行计算的符号,通常分为算数运算符.逻辑运算符.比较运算符和按位运算符. 1.算术运算符Object Pascal ...
- Java 文件IO
文件IO Java IO IO流用来处理设备之间的数据传输 Java对数据的操作是通过流的方式 Java用于操作流的对象都在IO包中 按操作数据分为 字节流和字符流 字符流的 ...
- iOS--获取输入字符的第一个字母(汉字则获取拼音的第一个字母)
- (NSString *)firstCharactor:(NSString *)aString { //转成了可变字符串 NSMutableString *str = [NSMutableStrin ...
- gradle资料
<Gradle用户教程>中文版 · GitBookhttps://www.gitbook.com/book/yeetrack/-gradle-user-guide-chinese/deta ...
- 2016最全的web前端面试题及答案整理
面试web前端开发,不管是笔试还是面试,都会涉及到各种专业技术问题,今天小编整理了一些常见的web前端面试题及答案,希望对大家有所帮助. 1.常用那几种浏览器测试?有哪些内核(Layout Engin ...
- phpstorm xdebug 碰到很神奇的一件事
早上配置好了,且正常运行了,然后没有退出phpstorm, 结果到了下午,配置消失了, 还好稳住了阵脚,然后配置了,就好了. 很重要一点,在调试观看源代码的时候,一定要浅薄,然后深入,不然累死,得不偿 ...
- xcode 脚本编译,打包ipa
1.清理工程 /usr/bin/xcodebuild -target targetName clean 2.编译 /usr/bin/xcodebuild -target targetName buil ...
- java 多线程3(线程安全)
需求:模拟三个窗口同时买票. 问题1:static 修饰num,只创建一份在内存中,要不就会创建3份. 问题2:线程安全问题.(代码重1的红色字体) 出现的原因:存在两个或两个以上的线程对象,而且线程 ...
- SAP中寄售处理
寄售分两种: 1, 供应商提供货物,我们销售 2,我们提供货物,寄售商销售 [@more@] 1, 供应商提供货物,我们销售 创建PO,购买寄售货物,categories维护成K,然后收货即可. 2, ...