1. 浅拷贝
- 浅拷贝只拷贝指针地址,它直接将一个对象的成员变量的值全部复制给新对象,可以认为是编译器默认生成的类实例间拷贝行为,对带有指针的类来说会引发二次释放等问题。
原理如图所示:
代码如下:
class Simple{
private:
int* _p;
public:
Simple(const Simple& s){
_p = s._p;
}
};
2. 深拷贝
- 深拷贝是用户自定义的一种构造函数, 对于存在的指针成员变量,重新分配内存,拷贝原来指向的内容,让指针指向新分配的内存。
原理如图所示:
代码如下:
class Simple{
private:
int* _p;
public:
Simple(const Simple& s){
_p = new int(*(s._p));
}
};
3. 写时拷贝
- 写时拷贝是对深拷贝的以种改良,深拷贝中即是我们指向的内容相同,却仍然要分配一块新的内存,重新定一个指针指向新分配的内存,这种方式非常浪费空间。我们可以利用计数器进行改进,既避免了二次释放的问题,又节约了空间。
原理如图所示:
实现代码如下:
#include <iostream>
#include <cstring>
using namespace std;
class String{
struct Data{
char* ptr;
size_t count;
Data(char* ptr, size_t count):ptr(ptr),count(count){}
};
Data* data;
public:
String(const char* str){
char* temp = new char[strlen(str)+1];
strcpy(temp, str);
data = new Data(temp, 1);
}
String(const String& s){
data = s.data;
++data->count;
}
String& operator=(const String& s){
if(this == &s || data == s.data) return *this;
--data->count;
if(0 == data->count){
delete [] data->ptr;
delete data;
}
data = s.data;
++data->count;
return *this;
}
~String(){
--data->count;
if(0 == data->count){
delete [] data->ptr;
delete data;
}
}
void Print(){
cout << data << ":" << data->count << ":" << data->ptr << endl;
}
};
int main(){
String s("Hello");
s.Print();
String s1(s);
s1.Print();
s.Print();
String s3("World");
s1 = s3;
s1.Print();
s3.Print();
}