• 写时复制


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

    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类的实现;

  • 相关阅读:
    [Java解惑]数值表达式
    Java使用LdAP获取AD域用户
    LDAP Error Codes
    Excel向上取整
    java中的三种取整函数
    Dwz手册的补充说明和常见问题
    【转】BSON数据格式
    go语言合并两个数组
    vscode远程修改文件('file': A system error occured )
    [转]Linux 桌面玩家指南:20. 把 Linux 系统装入 U 盘打包带走
  • 原文地址:https://www.cnblogs.com/zhengzhe/p/6542854.html
Copyright © 2020-2023  润新知