博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
string类的写时拷贝
阅读量:5301 次
发布时间:2019-06-14

本文共 2013 字,大约阅读时间需要 6 分钟。

由于浅拷贝使多个对象共用一块内存地址,调用析构函数时导致一块内存被多次释放,导致程序奔溃。

实现string类的时候通常显示的定义拷贝构造函数和运算符重载函数。

 

由于释放内存空间,开辟内存空间时花费时间,因此,在我们在不需要写,只是读的时候就可以不用新开辟内存空间,就用浅拷贝的方式创建对象,当我们需要写的时候才去新开辟内存空间。这种方法就是写时拷贝。 

在构造函数中开辟新的空间时多开辟4个字节的空间,用来存放引用计数器,记录这快空间的引用次数。

[cpp]
  1. #include<iostream>  
  2. #include<stdlib.h>  
  3. using namespace std;  
  4. class String  
  5. {  
  6. public:  
  7.      String(char *str = "")  
  8.       :_str(new char[strlen(str) + 5])  
  9.      {  
  10.           *(int *)_str = 1;  
  11.           _str += 4;  
  12.           strcpy(_str, str);  
  13.      }  
  14.      ~String()  
  15.      {  
  16.           if (_str != NULL)  
  17.           {  
  18.               _Release();  
  19.           }  
  20.      }  
  21.      String(const String& str)  
  22.      {  
  23.           _str = str._str;  
  24.           ++_GetRefCount();  
  25.      }  
  26.      String& operator=(const String& str)  
  27.      {  
  28.           if (this != &str)  
  29.           {  
  30.                _Release();  
  31.                _str = str._str;  
  32.                ++ _GetRefCount();  
  33.           }  
  34.           return *this;  
  35.      }  
  36.      char& operator[](int index)//写时拷贝  
  37.      {  
  38.    
  39.           if (_GetRefCount()>1)//当引用次数大于1时新开辟内存空间  
  40.           {  
  41.                --_GetRefCount();//原来得空间引用计数器减1  
  42.                char *str = new char[strlen(_str) + 5];  
  43.                strcpy(str+4, _str);  
  44.                _str = str+4;  
  45.                _GetRefCount()++;  
  46.           }  
  47.           return _str[index];  
  48.      }  
  49.      friend ostream& operator<<(ostream& output, const String& str)  
  50.      {  
  51.           output << str._str;  
  52.           return output;  
  53.      }  
  54.    
  55. private:  
  56.      int& _GetRefCount()  
  57.      {  
  58.           return *(int *)(_str - 4);  
  59.      }  
  60.      void _Release()  
  61.      {  
  62.           if (--_GetRefCount() == 0)  
  63.           {  
  64.                delete[] (_str-4);  
  65.           }  
  66.      }  
  67. private:  
  68.      char *_str;  
  69. }; 

 

 

==============》

 

将_pCount与_str所指向的空间放在一起,即只用new开辟一次空间

 

class String{	friend ostream& operator<<(ostream& os,String& s);public:	String(const char*str = "")		:_str(new char[strlen(str)+1+4])	{		*(int *)_str = 1;	//*_pCount = 1		_str = _str+4;	//找到数据存放的位置		strcpy(_str,str);		GetCount() = 1;	}	String(const String& str)		:_str(str._str)	{		++GetCount();	}	~String()	{		if(--GetCount() == 0)		{			delete[] (_str-4);		}	}	String& operator=(const String& s)	{		if (this != &s)		{			if (--GetCount() == 0)			{				delete[] (_str-4);  			}			++GetCount();			_str = s._str;		}		return *this;	}private:	int& GetCount()		//获得_pCount	{		return *((int *)_str-1);	}private:	char *_str;};ostream& operator<<(ostream& os,String& s){	os<
void test1(){	String str1("abcde");	String str2(str1);	String str3;	str3 = str2;	cout<
<

转载于:https://www.cnblogs.com/zhoug2020/p/6542467.html

你可能感兴趣的文章
Could not resolve view with name '***' in servlet with name 'dispatcher'
查看>>
Chapter 3 Phenomenon——12
查看>>
C语言中求最大最小值的库函数
查看>>
和小哥哥一起刷洛谷(1)
查看>>
jquery对id中含有特殊字符的转义处理
查看>>
遇麻烦,Win7+Ubuntu12.10+Archlinux12.10 +grub
查看>>
SqlBulkCopy大批量导入数据
查看>>
pandas 修改指定列中所有内容
查看>>
「 Luogu P2285 」打鼹鼠
查看>>
lua语言入门之Sublime Text设置lua的Build System
查看>>
vue.js基础
查看>>
电脑的自带图标的显示
查看>>
[转载] redis 的两种持久化方式及原理
查看>>
C++ 删除字符串的两种实现方式
查看>>
ORA-01502: 索引'P_ABCD.PK_WEB_BASE'或这类索引的分区处于不可用状态
查看>>
Java抽象类和接口的比较
查看>>
开发进度一
查看>>
MyBaits学习
查看>>
管道,数据共享,进程池
查看>>
CSS
查看>>