实现CMyString类--深拷贝与浅拷贝

实现CMyString类,实现赋值运算符函数(深拷贝与浅拷贝(写时拷贝))

深拷贝:赋值运算符函数说明

步骤1、释放原来的内存空间

步骤2、再重新开辟要赋值的对象的大小的空间

步骤3、再将另一个对象的值拷贝给this对象

友元函数的说明:由于输出重载需要俩个参数,不能再隐含this指针,故使用友元函数

代码如下:

<span style="font-size:18px;">class CMyString
{
public:
	CMyString()
		:str(new char[1])
	{
		str[0] = '\0';
	}
	CMyString(char* _str)
		:str(new char[strlen(_str)+1])
	{
		strcpy(str, _str);
	}
	CMyString(CMyString& s)
		:str(NULL)
	{
		delete[] str;
		str = new char[strlen(s.str) + 1];
		strcpy(str, s.str);
	}
	CMyString& operator=(CMyString& s)
	{
		if (this != &s)
		{
			delete[] str;
			str = new char[strlen(s.str) + 1];
			strcpy(str, s.str);
		}
		return *this;
	}
	~CMyString()
	{
		if (str)
		{
			delete[] str;
			str = NULL;
		}
	}
	friend ostream& operator<<(ostream& os,CMyString& s)
	{
		os << s.str;
		return os;
	}
private:
	char* str;
};</span>

浅拷贝:赋值运算符函数说明

步骤1、Release();

步骤2、将this->str 指向 s.str;

步骤3、++GetCount(str);

GetCount()函数说明:得到当前对象的引用计数--->*(int*)(str-4);

减4是因为对象在创建的时候除了多开辟了一个字节给‘|0’,还多给引用计数开辟了4个字节,且将str指向了引用计数的后4个字节(即字符串处),要得到引用计数需减4,如下图1:

Release()函数说明:判断str是否为空且引用计数减1之后是否为0;如果减1之后为0,说明后期无对象再去使用这块内存,则将其释放掉,反之不去释放;

写时拷贝char& operator[](size_t index);函数说明:

步骤1、减去引用计数

步骤2、拷贝

步骤3、创建引用计数

代码如下:

<span style="font-size:18px;">class CMyString
{
private:
	void Release()
	{
		if (str && --GetCount(str) == 0)
		{
			delete[](str - 4);
			str = NULL;
		}
	}
	int& GetCount(char* str)
	{
		return (*(int*)(str - 4));
	}
public:
	CMyString(char* _str = "")
		:str(new char[strlen(_str) + 5])
	{
		*(int*)str = 1;
		str += 4;
		strcpy(str, _str);
	}
	CMyString(const CMyString& s)
		:str(s.str)
	{
		++GetCount(str);
	}
	CMyString& operator=(const CMyString& s)
	{
		if (this != &s)
		{
			Release();
			str = s.str;
			++GetCount(str);
		}
		return *this;
	}
	//写时拷贝
	char& operator[](size_t index)
	{
		if (GetCount(str) > 1)
		{
			--GetCount(str);
			char* tmp = new char[strlen(str) + 5];
			tmp += 4;
			GetCount(tmp) = 1;
			strcpy(tmp, str);
			str = tmp;
		}
		return str[index];
	}
	~CMyString()
	{
		Release();
	}
	friend ostream& operator<<(ostream& os, CMyString& s)
	{
		os << s.str;
		return os;
	}
private:
	char* str;
};</span>

测试用例代码:

int main()
{
	CMyString s1("hello");
	CMyString s2;
	s2 = s1;
	CMyString s3 = s1;
	cout << s1 << endl;
	cout << s2 << endl;
	cout << s3 << endl;
	//浅拷贝中的写时拷贝测试用例
	s3[0] = 'b';
	s3[1] = 'l';
	s3[2] = 'k';
	cout << s3 << endl;
	return 0;
}

测试结果如下图2:

图1:

图2:

时间: 2024-10-27 10:14:12

实现CMyString类--深拷贝与浅拷贝的相关文章

C++ Primer 学习笔记_20_类与数据抽象(6)_深拷贝与浅拷贝、空类与空数组

C++ Primer 学习笔记_20_类与数据抽象(6)_深拷贝与浅拷贝.空类与空数组 一.深拷贝与浅拷贝 浅拷贝:被复制对象的所有变量都含有与原来的对象相同的值,而所有的对其他对象的引用仍然指向原来的对象.换而言之,浅拷贝仅仅复制所考虑的对象,而不复制它所引用的对象. 深拷贝:被复制对象的所有变量都含有与原来的对象相同的值,除去那些引用其他对象的变量.那些引用其他对象的变量将指向被复制过的新对象,而不再是原有的那些被引用的对象.换而言之,深拷贝把要复制的对象所引用的对象都复制了一遍. 浅拷贝可

C++ 类的深拷贝和浅拷贝完美解决

//类的深拷贝和浅拷贝 #define _CRT_SECURE_NO_WARNINGS #include<iostream> using namespace std; class Point{ public: Point(int _a,int _b,const char *pin/*in*/){ x = _a; y = _b; remark = (char *)malloc(sizeof(char)*(strlen(pin) + 1)); strcpy(remark, pin); cout &

从String类中看C++当中的深拷贝与浅拷贝解

了解过C++语言的人,都应该知道,C++语言中的构造函数,析构函数,拷贝构造函数,赋值运算符重载函数,如果不定义,编译器会自动生成的,当然,生成的只是一些最基本的,在达不到我们要求的条件下,就需要我们自己重新定义这些函数. 我们现在说的讲的是深拷贝与浅拷贝,当然讨论这个问题的基础,一般情况下是我们定义的变量是以指针形式出现的,原因就在于,不论赋值还是拷贝,我们要实现两个指针指向的内容一致,那我得到新的指针和原指针是指向同一块内存空间还是两块内存空间的相同内容.如果是指向同一块空间,就存在了安全隐

【转载】C++拷贝构造函数(深拷贝,浅拷贝)

对于普通类型的对象来说,它们之间的复制是很简单的,例如:int a=88;int b=a; 而类对象与普通对象不同,类对象内部结构一般较为复杂,存在各种成员变量.下面看一个类对象拷贝的简单例子. #include <iostream>using namespace std;class CExample {private:     int a;public:     CExample(int b)     { a=b;}     void Show ()     {        cout<

C++拷贝构造函数(深拷贝,浅拷贝)

http://www.cnblogs.com/BlueTzar/articles/1223313.html 对于普通类型的对象来说,它们之间的复制是很简单的,例如:int a=88;int b=a; 而类对象与普通对象不同,类对象内部结构一般较为复杂,存在各种成员变量.下面看一个类对象拷贝的简单例子. 1 #include <iostream> 2 using namespace std; 3 4 class CExample { 5 private: 6 int a; 7 public: 8

深拷贝与浅拷贝

一.浅拷贝和深拷贝 所谓浅拷贝,就是由默认的拷贝构造函数所实现的对数据成员逐一赋值.若类中含有指针类型的数据,这种方式只是简单的把指针的指向赋值给新成员,但并没有给新成员分配内存,因此这种方式必然会导致错误.为了解决浅拷贝出现的错误,必须显示的定义一个拷贝构造函数,使之不但复制数据成员,而且为对象分配各自的内存空间,这就是所谓的深拷贝. 二.浅拷贝 浅拷贝就是由默认的拷贝构造函数所实现的数据成员逐一赋值.通常默认的拷贝构造函数能够胜任这个工作,但是若类中含有指针类型的数据,这种数据成员逐一赋值的

【转】 C++的深拷贝与浅拷贝

对于普通类型的对象来说,它们之间的复制是很简单的,例如:int a=88;int b=a; 而类对象与普通对象不同,类对象内部结构一般较为复杂,存在各种成员变量.下面看一个类对象拷贝的简单例子. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 #include <iostream> using namespace std; class CExample { private:      int a; public:      CE

深拷贝,浅拷贝

深拷贝和浅拷贝对于基本变量是一样的,但是对于动态变量是不同的. 动态变量,对于C++/C是指针,对于JAVA是对象. 简单来说,对于C++,浅拷贝只是增加一个指针指向已经存在的内存,深拷贝是增加一个指针并且申请一个新的内存,使这个增加的指针指向这个新的内存.(这是递归的,即沿指针一层层往里追,直到获得了所有基本对象的副本) 浅拷贝可能造成内存溢出(从一个指针释放了内存,而另一个指针还在).多次释放(对同一块内存被多个指针释放) Java Object类的clone()方法是浅拷贝,可通过覆盖该方

【转】 c++拷贝构造函数(深拷贝,浅拷贝)详解

c++拷贝构造函数(深拷贝,浅拷贝)详解 2013-11-05 20:30:29 分类: C/C++ 原文地址:http://blog.chinaunix.net/uid-28977986-id-3977861.html 一.什么是拷贝构造函数      首先对于普通类型的对象来说,它们之间的复制是很简单的,例如: int a=100; int b=a; 而类对象与普通对象不同,类对象内部结构一般较为复杂,存在各种成员变量.  下面看一个类对象拷贝的简单例子. #include<iostream