在自己定义的String类中使用写实拷贝来提高效率。
写实拷贝是在浅拷贝的基础上使用引用计数器来拷贝对象,如果有对象被拷贝构造时只需要将计数器++,不用再开辟新的空间。
初版的代码:
#define _CRT_SECURE_NO_WARNINGS 1
#include<iostream>
using namespace std;
class String
{
public:
String(const char* str = "")
:_str(new char[strlen(str) + 1])
,_refcount(1)
{
strcpy(_str, str);
}
~String()
{
if (--_refcount == 0)
{
delete[]_str;
}
}
String(String& s)
:_str(s._str)
{
_refcount++;
}
private:
char* _str;
int _refcount;
};
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
因为计数器是私有的,所以每个对象的计数器都为1,释放空间时系统会奔溃。
我们还可以将_refcount设置为static静态,为对象共有。但是static是全局变量,所以创建不同对象时_refcount会出现问题。
所以可以直接再开辟一个空间用来存储计数器个数 ,使用一个指针指向这块空间,这样拷贝构造时只需要将对象指针指向计数器,将计数器内容++,释放对象空间时,如果计数器个数不为1,则直接计数器内容–,为1证明只有一个对象指向这块空间,则释放计数器空间,释放字符串空间。
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
-
#define _CRT_SECURE_NO_WARNINGS 1
#include<iostream>
using namespace std;
class String
{
public:
String(const char* str = "")
:_str(new char[strlen(str) + 1])
, _refptr(new int(1))
{
strcpy(_str, str);
}
~String()
{
if (--(*_refptr) == 0)
{
delete[]_str;
delete _refptr;
}
}
String(String& s)
:_str(s._str)
, _refptr(s._refptr)
{
(*_refptr)++;
}
String& operator=(String& s)
{
if (_str != s._str)
{
if (--(*_refptr) == 0)
{
delete[]_str;
delete _refptr;
}
_str = s._str;
_refptr = s._refptr;
(*_refptr)++;
}
return *this;
}
private:
char* _str;
int* _refptr;
};