写时复制

概念:在有些大型类中复制一个类要花费大量时间。

TString one("abcd");

TString two(one);

这时写时复制就可以解决这个问题,所有复制对象共用原对象,当要改变对象的数据成员时才产生一个新的副本。

 .head

 1 #pragma once
 2 #include<iostream>
 3 #include<string>
 4 #include<stdlib.h>
 5 #include<ctype.h>
 6 using namespace std;
 7 
 8 class TString
 9 {
10 public:
11     //输入/输出操作符
12     //构造函数,创建一个空字符对象
13     TString();
14     //创建一个字符串对象,该对象包含指向字符的s指针
15     //s必须以NULL结尾,从s中复制字符
16     TString(const char* s);
17     //创建一个包含单个字符aChar的字符串
18     TString(char aChar);
19     TString(const TString& arg);//拷贝构造函数
20     ~TString();//析构函数
21                //赋值操作符
22     TString& operator=(const TString& arg);
23     TString& operator=(const char* s);
24     TString& operator=(char aChar);
25     //返回对象当前储存的字符个数
26     int Size() const;
27     //返回posn中len长度的子字符串
28     TString operator()(unsigned posn, unsigned len) const;
29     //返回下表为n的字符
30     char operator()(unsigned n) const;
31     //返回对下标为n的字符的引用
32     const char& operator[](unsigned n) const;
33     //返回指向内部数据的指针,当心
34     const char* c_str()const { return _str; };
35     //以下方法将修改原始对象。
36     //把其他对象中的字符附加在*this后
37     TString& operator+=(const TString& other);
38     //在字符串中改动字符的情况
39     TString& ToLower();//将大写字符转换成小写
40     TString& ToUpper();//将小写字符转换成大写
41 private:
42     struct StringRep
43     {
44         char *_str;//实际的字符
45         unsigned _refCount;//对它的引用的数目
46         unsigned _length;//字符串中的字符数目
47     };
48     StringRep *_rp; //再TString中唯一的数据成员;
49 
50 };
51 
52 //支持TString类的非成员函数
53 //返回一个新TSring类的对象,该对象为one和two的级联
54 TString operator+(const TString& one, const TString& two);
55 //输入/输出操作符
56 ostream& operator<<(ostream& o, const TString& s);
57 istream& operator >> (istream& stream, TString& s);
58 //关系操作符,基于ASCII字符集比较。
59 //如果两字符串对象包含相同的字符,则两对象相等。
60 bool operator==(const TString& first, const TString& second);
61 bool operator!=(const TString& first, const TString& second);
62 bool operator<(const TString& first, const TString& second);
63 bool operator>(const TString& first, const TString& second);
64 bool operator>=(const TString& first, const TString& second);
65 bool operator<=(const TString& first, const TString& second);

.cpp;

  1 #include "TString.h"
  2 
  3 
  4 
  5 TString::TString()
  6 {
  7     _rp = new StringRep;
  8     _rp->_refCount = 1;
  9     _rp->_length = 0;
 10     _rp->_str = 0;
 11 }
 12 
 13 
 14 TString::TString(const char* s)
 15 {
 16     _rp = new StringRep;
 17     _rp->_refCount = 1;
 18     _rp->_length = strlen(s);
 19     _rp->_str = new char[_rp->_length + 1];
 20     strcpy(_rp->_str, s);
 21 }
 22 
 23 TString::TString(char aChar)
 24 {
 25     _rp = new StringRep;
 26     _rp->_refCount = 1;
 27     _rp->_length = 1;
 28     _rp->_str = new char[_rp->_length + 1];
 29     _rp->_str[0] = aChar;
 30     _rp->_str[1] = 0;
 31 }
 32 
 33 
 34 TString::TString(const TString& other)
 35 {
 36     //这时重要的操作之一;
 37     //我们需要再other中,通过_rp所指向的对象递增引用计数。它又获得一个引用。
 38     other._rp->_refCount++;
 39     //让它们共享资源
 40     this->_rp = other._rp;
 41 }
 42 
 43 TString& TString::operator=(const TString& other)
 44 {
 45     if (this == &other)
 46         return *this;//自我赋值
 47     /*这时另一个重要的操作。我们需要再other中,通过_rp所指向的对象递增引用计数。
 48     同时,需要用过this指向的对象递减引用计数*/
 49     other._rp->_refCount++; //它又获得一个引用
 50     //递减和测试,是否仍然再使用它
 51     if (--this->_rp->_refCount == 0)
 52     {
 53         delete[]this->_rp->_str;
 54         delete this->_rp;
 55     }
 56     this->_rp = other._rp;//共享资源;
 57     return *this;
 58 
 59 }
 60 
 61 
 62 
 63 //这是一个重要的成员函数,需要应用“写时复制”方案
 64 TString& TString::ToLower()
 65 {
 66     char *p;
 67     if (_rp->_refCount > 1)
 68     {
 69         //这是最困难的部分。分离TString对象并提供它的StringRep对象;
 70         //这是“写时复制”操作
 71         unsigned len = this->_rp->_length;//保存它
 72         p = new char[len + 1];
 73         strcpy(p, this->_rp->_str);
 74         this->_rp->_refCount--;//因为*this即将离开内存池;
 75         this->_rp = new StringRep;
 76         this->_rp->_refCount = 1;
 77         this->_rp->_length = len;
 78         this->_rp->_str = p;//p在前面已创建
 79     }
 80 
 81     //继续,并改变字符
 82     p = this->_rp->_str;
 83     if (p != 0)
 84     {
 85         while (*p)
 86         {
 87             *p = tolower(*p);
 88             ++p;
 89         }
 90     }
 91     return *this;
 92 }
 93 
 94 TString& TString::ToUpper()//和tolower的相似方法
 95 {
 96     return *this;
 97 }
 98 
 99 
100 
101 TString::~TString()
102 {
103     if (--_rp->_refCount == 0)
104     {
105         delete[] _rp->_str;
106         delete _rp;
107     }
108 }
109 
110 //省略其他函数的实现;

思考:在上面的代码中,很多地方都需要创建、删除和操控StringRep对象。很明显,这并不是最好的方法。尝试修改实现,以便StringRep有自己的构造

函数、析构函数以及其他函数。这样,StringRep便可自我管理。另外,完成TString类的实现;

原文地址:https://www.cnblogs.com/zhengzhe/p/6542854.html