赞
踩
在实现string类时不能用简单的浅拷贝去实现,因为浅拷贝会简单让两个对象指向同一块空间,这样的缺陷是两者指向同一块空间,析构时会出现程序崩溃的问题,两个对象管理同一块空间,一改都改,这显然是你所不期待的。
所以深拷贝就应运而生,所谓的深拷贝就是在用A对象拷贝B对象时,为B对象开辟与A对象一样大的空间,大家各自管理自己的空间。
下面简单的去实现一下深拷贝。
#include<iostream>
#include<cstring>
using namespace std;
class String
{
public:
String(char* str = "")
:_str(new char[strlen(str) + 1])
{
strcpy(_str, str);
}
~String()
{
delete[] _str;
}
传统写法
//String(const String& str)
// :_str(new char[strlen(str._str) + 1])
//{
// strcpy(_str, str._str);
//}
//String& operator=(const String& str)
//{
// /*if (this != &str)
// {
// delete[] _str;
// _str = new char[strlen(str._str) + 1];
// strcpy(_str, str._str);
// }
// return *this;*/
// char* tmp = new char[strlen(str._str) + 1];
// strcpy(tmp, str._str);
// delete[] _str;
// _str = tmp;
// return *this;
//}
//现代写法
String(const String& str)
:_str(NULL)
{
String tmp(str._str);
swap(_str, tmp._str);
}
//值传递过来的str是已经创建好的临时空间,这块空间的内容正是我想要的
String& operator=(String str)
{
swap(_str, str._str);
return *this;
}
char* Getstr()
{
return _str;
}
private:
char* _str;
};

上面呢就是string类的深拷贝,在写深拷贝时提供了现代写法与传统写法,推荐使用现代写法,优势在于效率更高,代码复用性更强,益于管理。
有了深拷贝,这个string类的实现是没有问题的,但是思考一下引入深拷贝,有两方面的原因,一:同一块空间析构多次会出现问题,二:一改多改,与实际需求不否。
现在假设我们已经解决了问题一,(记住管理这块空间有多少个对象,在无对象管理时将其析构),问题二的产生是在我需要修改时才会发生的问题,如果我创建出来不需要修改,只是用来读,这时多开辟的空间显然是有点浪费的。故此引入了写时拷贝,解决问题一可以用引用计数来搞定。
再具体写写时拷贝前,先简单的介绍下引用计数。
引用计数呢是用来统计这块空间现在又多少对象在管理,是一个计数器,所以呢我们可以在构造这个对象时对开辟四个字节用来存储这个ReferenceCount。
下面呢简单的实现一下。
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
using namespace std;
class String
{
public:
String(char* str = "")
:_str(new char[(strlen(str) + 5)])
{
*((int*)_str) = 1;
str += 4;
strcpy(_str, str);
}
String(const String& s)
{
_str = s._str;
++GetRefCount();
}
String& operator=(const String& s)
{
if (_str != s._str)
{
if (--(GetRefCount()) == 0)
{
delete[] _str;
}
_str = s._str;
++(GetRefCount());
}
return *this;
}
~String()
{
if (--(GetRefCount()) == 0)
{
delete[] (_str - 4);
}
}
int& GetRefCount()
{
return *((int*)(_str - 4));
}
private:
char* _str;
};

上面就是string类的基本实现,如果需要修改则需要重新开辟空间(多个对象管理),这是查的话则不需要。
备注:
写时拷贝是否不会出错呢?这显然是不可能的,再好的代码也会出错。写时拷贝在单线程时不会出错,但如果是多线程的话还是会出现问题。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。