String类 (浅拷贝/深拷贝/写时拷贝)
来源:互联网 发布:ipad看图软件 编辑:程序博客网 时间:2024/06/05 01:01
浅拷贝是指当对象的字段值被拷贝时,字段引用的对象不会被拷贝。例如,如果一个对象有一个指向字符串的字段,并且我们对该对象做了一个浅拷贝,那么两个对象将引用同一个字符串。
存在问题:
如果源程序中没有显示定义拷贝构造函数,在进行对象的拷贝时,将调用系统默认的拷贝构造函数,这就使得两个对象指向了同一资源,而析构函数又在对象生命周期结束后可以释放空间,势必会两次返还空间,编译器就会报错。
这时就需要用到深拷贝了。
深拷贝的两种版本:
#define _CRT_SECURE_NO_WARNINGS 1 #include<iostream>using namespace std;//#if 0class String{public: String(char *pStr = "") //构造函数 { if (NULL == pStr) { _pStr = new char[1]; *_pStr = 0; } else { _pStr = new char[strlen(pStr) + 1]; strcpy(_pStr, pStr); } } //简洁版 ////拷贝构造函数 1 //String(const String &s) // :_pStr(new char[strlen(s._pStr) + 1]) //{ // String temp(s._pStr); // swap(_pStr, temp._pStr); //} ////拷贝构造函数 2 //String(const String &s) // :_pStr(NULL) //{ // _pStr = new char[1]; // String temp(s._pStr); // swap(_pStr, temp._pStr); //} //普通版 String(const String &s) :_pStr(new char[strlen(s._pStr) + 1]) { strcpy(_pStr, s._pStr); } //赋值运算符重载 /* //由于pTemp在栈上,出了函数将销毁,故错误 String &operator=(const String &s)//赋值运算符重载 { if (this != &s) { char *pTemp = new char[strlen(s._pStr) + 1];// pTemp在栈上 strcpy_s(pTemp, strlen(s._pStr), s._pStr); //strcpy_s(_pStr, strlen(pStr), pStr); delete[] _pStr; _pStr = pTemp; } return *this; } */ //赋值运算符重载 1 /* String &operator=(const String &s) { //if (this != &s) 赋值运算符重载的反例,会造成一块空间多次释放 //{ // _pStr = s._pStr; //} //return *this; if (this != &s) { String temp(s._pStr);//用S里面的字符串构造一个临时的temp swap(_pStr, temp._pStr);//交换两个指针 } return *this; } */ //赋值运算符重载 2 String& operator=(const String& pStr) { if (this != &pStr) { //防止new开辟内存失败,丢失原来内存 char* ptr = new char[strlen(pStr._pStr) + 1]; strcpy(ptr, pStr._pStr); delete[]_pStr; _pStr = ptr; } return *this; } ~String() //析构函数 { if (this != NULL) { delete[] _pStr; _pStr = NULL;//可有可无 } } friend ostream& operator<<(ostream & _cout, const String&pStr);private: char *_pStr;};//输出流重载ostream& operator<<(ostream & _cout, const String&pStr){ _cout << pStr._pStr << endl; return _cout;}void FunTest1(){ String s1("hello"); cout << "s1=" << s1 << endl; String s2(s1); //调用拷贝构造函数 cout << "s2=" << s2 << endl;}void FunTest2(){ String s3("word"); String s4; s4 = s3; //调用赋值运算符重载 cout << "s3=" << s3 << endl; cout << "s4=" << s4 << endl;}int main(){ FunTest1(); FunTest2(); getchar(); return 0;}//#endif
1、开辟两个空间的计数,代码如下:
#include<iostream>using namespace std;class String{public: String(const char * pStr = "")//构造函数 :_pCount(new int(1)) //_pCount初始化为1 { if (NULL == pStr) { _pStr = new char[1]; *_pStr = '\0'; } else { _pStr = new char[strlen(pStr) + 1]; strcpy(_pStr, pStr); } } String(const String &s)//拷贝构造函数 :_pStr(s._pStr) , _pCount(s._pCount) { ++*_pCount;//调用一次拷贝构造函数_pCount++ } //赋值运算符重载 String & operator = (const String & s) { if (this != &s) { if (0 == --*_pCount) { delete[] _pStr; delete _pCount; } _pStr = s._pStr; _pCount = s._pCount; ++*_pCount; } } ~String()//调用析构函数时 先--_pCount,判断是否为0 { if ((_pStr) && (0 == --*_pCount)) { delete[] _pStr; _pStr = NULL; delete _pCount; _pCount = NULL; } } friend ostream& operator<<(ostream & output, const String &s);private: char * _pStr; int * _pCount;};ostream& operator<<(ostream & output, const String &s)//输出流的重载{ output << s._pStr << endl; return output;}void FunTest(){ String s1("hello"); cout << "s1=" << s1 << endl; String s2(s1); cout << "s2=" << s2 << endl; String s3("heihei"); cout << "s3=" << s3 << endl; String s4 = s3; cout << "s4=" << s4 << endl;}int main(){ FunTest(); getchar(); return 0;}
运行结果:
2、一个空间的计数,代码如下:
class String//{//public:// String(char* ptr = NULL)// {// if (ptr == NULL)// {// _ptr = new char[5];// *(_ptr + 4) = 0;// }// else// {// _ptr = new char[strlen(ptr) + 5];// strcpy(_ptr + 4, ptr);// }// *(int*)_ptr = 1;// }// String(const String& s)// :_ptr(s._ptr)// {// (*(int*)_ptr)++;// }// String& operator=(const String& s)// {// if (&s != this)// {// _ptr = s._ptr;// (*(int*)_ptr)++;// }// return *this;// }// ~String()// {// if (--*(int*)_ptr == 0)// {// delete[] _ptr;// _ptr = NULL;// }// }//private:// char* _ptr;//};class String{public: String(const char* pStr) { if (pStr == NULL) pStr = " "; _pStr = new char[strlen(pStr) + 1 + 4];//多开辟4个字节 _pStr += 4; strcpy(_pStr, pStr); GetReference() = 1; } String(const String&s) :_pStr(s._pStr) { ++ GetReference(); } String & operator = (const String & s) { if (this != &s) { if (--GetReference() = 0) { _pStr -= 4; delete[] _pStr; } _pStr = s._pStr; ++GetReference(); } } ~String() { if ((--GetReference() == 0) && _pStr) { _pStr -= 4; delete[] _pStr; _pStr = NULL; } } friend ostream & operator<<(ostream &output, String &s);private: int& GetReference() { return *(int*)(_pStr - 4); } char* _pStr;};ostream & operator<<(ostream &output, String &s){ output << s._pStr << endl; return output;}void FunTest(){ String s1("ximenchuixue"); cout << "s1=" << s1 << endl; String s2(s1); cout << "s2=" << s2 << endl; String s3("sikongzhaixing"); cout << "s3=" << s3 << endl; String s4 = s3; cout << "s4=" << s4 << endl;}int main(){ FunTest(); getchar(); return 0;}
运行结果:
阅读全文
1 0
- String类 (浅拷贝/深拷贝/写时拷贝)
- String类的拷贝(浅拷贝,深拷贝,写时拷贝)
- string类深拷贝,写时拷贝
- String类详解(浅拷贝,深拷贝,引用计数,写时拷贝)
- String类的自我认知(浅拷贝、深拷贝、写时拷贝)
- string类,浅拷贝,深拷贝(简洁版),写时拷贝
- 【C++】浅析浅拷贝,深拷贝及写时拷贝(copy_on_write),模拟实现String类。
- 用string剖析浅拷贝、深拷贝、写时拷贝
- 深拷贝&浅拷贝&写时拷贝
- String类的浅拷贝、深拷贝、引用计数、写时拷贝
- 面试题:String类的浅拷贝、深拷贝、写时拷贝
- 浅拷贝、深拷贝(普、简)、写时拷贝
- String类---深拷贝,简洁深拷贝,引用计数拷贝,写时拷贝
- String类(深/浅拷贝、引用计数、写时拷贝)
- String类的浅拷贝,深拷贝
- string类的浅拷贝,深拷贝,写实拷贝
- 【C++】深拷贝、浅拷贝和写时拷贝
- 浅拷贝、深拷贝与写时拷贝
- offer34--丑数
- spring boot中出现parent报错
- Vue之计算属性
- SpringBoot微服务之分布式跟踪系统(springboot+zipkin)
- python之matplotlib画图库学习绘制常用的图
- String类 (浅拷贝/深拷贝/写时拷贝)
- 实现轮胎印
- 微服务之分布式跟踪系统(springboot+zipkin+mysql)
- redis的安装
- UICC之UiccCard
- python循环输出三角形图案
- MyBatis初窥:HelloWorld
- 动态规划-再次理解最长上升子序列
- 洛谷 1433 吃奶酪 dfs+剪枝