一、浅拷贝
1、概念:浅拷贝就是当在进行对象的复制时,只是进行对象数据成员的拷贝,其中默认的拷贝构造函数也是浅拷贝。
大多数情况下使用浅拷贝时没有任何问题的,但是当出现动态成员就会出现问题。
2、当浅拷贝时。出现了动态成员,当调用析构函数时,一块内存就有可能出现多次析构。
二、写时拷贝
1.引用计数的拷贝时用来解决浅拷贝存在的问题,所以它也是一种浅拷贝。
class String
{
private:
char*_str;
int*_refCount;
}
2.我们为每个内存的字符数组添加一个引用计数refCount,即就是在构造函数申请空间的时候多申请4个字节空间。
表示有多少个对象使用这块内存,有多少个对象使用,就让refCount值加一,当对象被析构的时候,让refCount
值减一,当refCount值为0时,将这块内存释放掉。当然refCount也要实现内存共享,所以它也是一个堆中的数据,
如果一个对象第一次开辟空间存放字符串,再开辟空间存放新的引用计数都指向存放引用计数的同一块空间,refCount
设置成int*就可以了,但是存在缺陷。(一、每次new两块空间,创建多个对象的时候效率比较低;二、它多次分配小
块空间容易造成内存小块化,导致分配不出来大块内存)
#include<iostream>
#include<string.h>
using namespace std;
class String
{
public:
String(char*ptr = "")
{
if (ptr == NULL)
{
_ptr = new char[strlen(ptr) + 5];
_ptr = new char[5];
*(_ptr) = '\0';
}
else
{
_ptr = new char[strlen(ptr) + 5];
*((int*)_ptr) = 1;
_ptr += 4;
strcpy(_ptr, ptr);
}
}
String(const String&s)
:_ptr(s._ptr)
{
(*((int*)(_ptr - 4)))++;
}
String& operator=(const String& s)
{
if (this != &s)
{
if (--(*((int*)(_ptr - 4))) == 0)
{
delete[]_ptr;
}
else
{
_ptr = s._ptr;
++(*(int*)(_ptr - 4));
}
}
return *this;
}
~String()
{
if ((_ptr != NULL) && ((--(*((int*)(_ptr - 4))))))
{
delete[]_ptr;
_ptr = NULL;
}
}
private:
char*_ptr;
};
void Funtest()
{
String s1("hello");
String s2(s1);
String s3(s2);
s3 = s1;
}
int main()
{
Funtest();
return 0;
}