深浅拷贝与写时拷贝
来源:互联网 发布:病态矩阵特征值 编辑:程序博客网 时间:2024/05/24 00:13
在c++中,基本所有的类都要考虑深拷贝,浅拷贝与写时拷贝,根据不同的定义,选择适合自己的拷贝方式。时间类就可以用浅拷贝,而二叉树,string类就需要深拷贝。
string类在vs编译器下使用的深拷贝,在Linux下使用的浅拷贝。
为什么会存在深浅拷贝的问题呢?
string的浅拷贝是让两个不同的指针指向同一块空间,而这在析构的时候会出现将一块空间释放两次,程序会崩溃,因此我们才需要进行深拷贝,即第二个指针开辟和第一个指针一样大小空间,然后将内容复制过去。
深拷贝:
ass string{public: string(char* pstr) //构造函数 :str(new char[strlen(pstr) + 1]) //开辟新的空间 { if (pstr == NULL)// { str = new char[1]; //开辟一个 存放‘\0’ *str = '\0'; } else { str = new char[strlen(pstr) + 1]; for (size_t i = 0; i < strlen(pstr); i++) //深复制 { str[i] = pstr[i]; } //strcpy(str,pstr); //memcpy(str,pstr,strlen(pstr)+1);浅复制 } } //拷贝构造函数 string(const string& pstr) :str(new char[strlen(pstr.str)+1]) { for (size_t i = 0; i < strlen(pstr.str); i++) { str[i] = pstr.str[i]; } //strcpy(str,pstr.str); //memcpy(str,pstr.str,strlen(pstr.str)+1); } //赋值运算符重载 string& operator = (const string & pstr) { if (&str == &pstr.str) //检查是否是自己给自己赋值 return *this; delete[] str; //释放临时空间 str = new char[strlen(pstr.str) + 1]; for (size_t i = 0; i < strlen(pstr.str); i++) { str[i] = pstr.str[i]; } //strcpy(str,pstr.str); //memcpy(str,pstr.str,strlen(pstr.str)+1); return *this; } /*现代写法: 根据拷贝构造函数让系统自己开辟空间 拷贝构造函数 string(const string& pstr) :str=null; 必须置为空,要不然访问地址非法化 { string tmp (pstr); swap(tmp.str,str); return *this; } 赋值运算符重载 string& operator = (const string& pstr ) { string tmp(pstr); swap(tmp.str, str); return *this; }*/ //析构函数 ~string() { delete[] str; str = NULL; }private: char* str;};int main(){ string a ("12345"); string b(a); cout << b << endl;}
浅拷贝,当我们需要改变新的空间的内容的时候,才会重新开辟空间呢?
1)判断空间使用的次数来选择析构,增加一个类成员 count,但是这样造成的后果是每一个成员都有一个不同的count 在析构的时候就很混乱还是会出错
2)然后呢我们会想到使用静态成员的办法,因为此时 static int count 是放在静态区,它是所有对象共享的,不会为每个对象单独生成一个count,可是当我们有多个不同的成员共同管理一块空间,而此时我们又用构造函数创建一个对象时候,count又会变为1,所以这种方法还是不行 。
3)使用引用计数,把引用计数放在字符串的前四个字节里,每个创建出来的对象都有不同的引用计数
class string{public: string(char* pstr) //构造函数 :str(new char[strlen(pstr) + 1+4])//多开辟的4个字节存放引用计数 { if (pstr == NULL) { str = new char[1]; *str = '\0'; } else { str = new char[strlen(pstr) + 1+4]; int* count = (int* )str; *count = 1; count ++; //后移拷贝数据 str = (char*)count; for (size_t i = 0; i < strlen(pstr); i++) //深复制 { str[i] = pstr[i]; } //strcpy(str,pstr); //memcpy(str,pstr,strlen(pstr)+1);浅复制 } } //拷贝构造函数 string(const string& pstr) { str = pstr.str; int * count = (int *)(str-4) ; ++*count; } //赋值运算符重载 string& operator = (const string & pstr) { if (&str == &pstr.str) return *this; destroy();//判断是否释放空间 str = pstr.str; int * count = (int *)(str-4) ; ++*count; }void destroy(){ int * count = (int *)(str-4); //获取引用计数 if(*count == 1) { delete[](str-4); str = NULL; } else --*count;}//析构函数~string(){ destroy();}private: char* str; int * count;};
写时拷贝:
在浅拷贝中,假设有多个名称引用了同一个字符串,当其中一个需要修改字符串时,这就会导致引用的值发生改变,这明显不是我们所期望的,所以出现了写时拷贝,(可能会修改字符串的时候使用深拷贝将其与大部队分离,这样就保护了其他引用成员)
则我们只需要重载[] 就可以实现
const string& operator[]const { string tmp(pstr); swap(tmp.str, str); return *this;}
阅读全文
0 0
- 深浅拷贝与写时拷贝
- 深浅拷贝与写时拷贝的简单认知
- c++深浅拷贝&写时拷贝实现
- C++String深浅拷贝、写时拷贝
- 深浅拷贝和写时拷贝
- 深浅拷贝&引用计数写时拷贝
- C++中的深浅拷贝和写时拷贝
- string的深浅拷贝以及写时拷贝问题
- 【c++】深浅拷贝,引用计数写时拷贝
- 深浅拷贝
- 深浅拷贝
- 深浅拷贝
- 深浅拷贝
- 深浅拷贝
- 深浅拷贝
- 深浅拷贝
- 深浅拷贝
- 深浅拷贝
- Android 7.1.1 来一个未接电话后不查看,关机后再开机状态栏不显示未接图标
- Android使用protobuf
- 指针C++
- orcl中的trim函数练习
- 【tensorflow学习】最简单的GAN 实现
- 深浅拷贝与写时拷贝
- Android init language
- python爬虫----爬取糗事百科
- 从mysql获取表转化为hive建表语句(python语言)
- Vasya and String(尺取 贪心)
- Spark Structured Streaming入门编程指南
- [Android]笔记16:网格视图(GridView)的功能与用法
- 2017暑期集训 Day 3
- script标签的属性 async 和 defer 的区别