深浅拷贝

【浅拷贝】

      又称位拷贝,编译器只是直接将指针的值拷贝过来,结果多个对象共用同一块内存,当一个对象将这块对象释放掉之后,其他对象不知道该内存已经还给了系统,以为还有效,所以在这段内存进行操作的时候,发生了错误。

#include<iostream>
using namespace std;
#include<cstring>
class String
{
public:
	String(const char *str)//构造函数
		:_str(new char(strlen(str)+1))
	{
		strcpy(_str, str);
	}

	String& operator=(const String& str)//赋值运算符
	{
		if (this != &str)//不是自己给自己赋值
		{
			_str = str._str;
		}
		return *this;
	}
	~String()//析构函数
	{
		if (NULL != _str)
		{
			delete[] _str;
			_str = NULL;
		}
	}
private:
	char *_str;
};
int main()
{
	String s1("hello world!");
	String s2 = s1;
	system("pause");
	return 0;
}

结果出错:


原因:


【深拷贝】


#include<iostream>
using namespace std;
#include<string.h>
#include<assert.h>
class String
{
public:
	String()
	{}
	String(const char *str)//构造函数
		:_size(strlen(str) + 1)
	{
		_str = new char[_size];
		strcpy(_str, str);
		_str[_size] = '\0';
	}
	String(const String& str)//拷贝构造
		:_size(str._size)
	{
		_str = str._str;
	}
	String& operator=(const String& str)//赋值运算符
	{
		if (this != &str)//不是自己给自己赋值
		{
			_str = str._str;
			_size = str._size;
		}
		return *this;
	}
	~String()//析构函数
	{
		if (NULL != _str)
		{
			delete[] _str;
			_str = NULL;
			_size = 0;
		}
	}
	void print()//打印
	{
		if (this != NULL)
		{
			cout << _str << endl;
		}
	}

	int Size()const//获取字符串长度
	{
		return _size;
	}

	bool operator==(const String &s)//比较两个字符串是否相等
	{
		if (_size != s._size)
		{
			return false;
		}
		return strcmp(_str, s._str) ? false:true;
	}
	bool operator!=(const String &s)//比较两个字符串是否不相等
	{
		return !(*this == s);
	}
	bool operator<(const String &s)//比较当前字符串是否小于s
	{
		int i = 0;
		while (_str != '\0' && s._str != '\0')
		{
			if (_str[i] < s._str[i])
			{
				return true;
			}
			else if (_str[i] > s._str[i])
			{
				return false;
			}
			i++;
		}
		if (_str == '\0')
		{
			return true;
		}
		return false;
	}
	bool operator<=(const String &s)
	{
		return (*this < s) || (*this == s);
	}
	bool operator>(const String &s)
	{
		return !(*this <= s);
	}
	bool operator>=(const String &s)
	{
		return (*this > s) || (*this == s);
	}

	void remove(size_t n,size_t len)//删除指定长度的元素
	{
		for (int i = (int)n; i < _size; i++)
		{
			_str[i] = _str[i + len];
		}
		_size -= len;
	}
	void Insert(int n,const char* s)//在指定位置插入元素
	{
		assert(n < _size);
		int len = strlen(s);
		for (int i = _size; i >= (int)n; i--)
		{
			_str[i + len] = _str[i];
		}
		while (*s != '\0')
		{
			_str[n++] = *s++;
		}
		_size += len;
	}
private:
	char *_str;//字符串
	int _size;//长度
};
int main()
{
	char array[] = "hello wrold";
	String s1(array);
	s1.print();
	String s2(s1);
	s2.print();
	String s3;
	s3 = s1;
	s3.print();
	cout << endl;

	String s("hello wrold!");
	cout << s.Size() << endl;
	cout << endl;

	cout << s2.operator==(s1) << endl;
	cout << s3.operator!=(s1) << endl;
	cout << endl;

	String s4("hello");
	String s5("hello");
	cout << s4.operator<(s5) << endl;
	cout << s4.operator<=(s5) << endl;
	cout << s4.operator>(s5) << endl;
	cout << s4.operator>=(s5) << endl;
	cout << endl;

	String S1("hi!!!!!!");
	S1.print();
	S1.remove(1,3);
	S1.print();
	S1.Insert(4, "hello");
	S1.print();
	system("pause");
	return 0;
}

【写时拷贝】

浅拷贝的两个问题?

1、释放多次——用引用计数解决

2、一个修改了会影响另一个——用写时拷贝解决

String的三种写时拷贝:

方案一:


方案二:


方案三:


第三种方案最合适

#include<iostream>
using namespace std;
class String
{
public:
	String(const char* str)//构造函数
		:_str(new char[strlen(str) + 5])
	{
		_str += 4;//跳过计数器的4个字节
		strcpy(_str, str);
		//*((int*)(_str - 4)) = 1;//给计数器赋值,不会改变_str
		GetRefCount() = 1;//给计数器赋值
		//(int)(_str - 4) = 1;//不行,左值不可以变
	}
	//s2(s1)
	String(const String& s)//拷贝构造
		:_str(s._str)
	{
		GetRefCount()++;
	}
	//s3=s1
	String& operator=(const String& s)
	{
		//if (this != &s)只能判断s1=s1,不能判断s1=s2(s1、s2本身就指向同一块空间)
		if (_str != s._str)//不是自己给自己赋值
		{
			if ((--GetRefCount()) == 0)//引用计数为0才释放其空间
			{
				delete[] (_str - 4);
			}
			_str = s._str;
			GetRefCount()++;//让this来调用,不让s来调用
		}
		return *this;
	}
	//写时拷贝
	void CopyOnWrite()
	{
		if (GetRefCount() > 1)
		{
			--GetRefCount();
			char* tmp = new char[strlen(_str) + 5];
			tmp += 4;
			strcpy(tmp, _str);
			GetRefCount() = 1;
		}
	}
	char& operator[](size_t pos)
	{
		CopyOnWrite();
		return _str[pos];
	}
	const char& operator[](size_t pos)const
	{
		return _str[pos];
	}
	int& GetRefCount()//获取计数器内的数字
	{
		return *((int*)(_str - 4));
	}
	~String()//析构函数
	{
		if (--GetRefCount() == 0)//判断计数器是否为0
		{
			delete[] (_str - 4);//释放计数器占用的空间
		}
	}
private:
	char *_str;
};
int main()
{
	String s1("hello");
	String s2(s1);
	String s3("hello world");
	cout << s1.GetRefCount() << endl;
	cout << s2.GetRefCount() << endl;
	cout << s3.GetRefCount() << endl;
	cout << endl;
	s1 = s3;
	cout << s1.GetRefCount() << endl;
	cout << s2.GetRefCount() << endl;
	cout << s3.GetRefCount() << endl;

	cout << s1[0] << endl;

	cout << s1.GetRefCount() << endl;
	cout << s2.GetRefCount() << endl;
	cout << s3.GetRefCount() << endl;
	system("pause");
	return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值