String类的三种实现

  • 浅拷贝
 class String
{
public:
String(const char* pdata)//构造函数
:_pdata(new char[strlen(pdata) + ])
{
strcpy(_pdata, pdata);
}
String(const String&s)//拷贝构造
:_pdata(s._pdata)
{}
~String()//析构函数
{
if (NULL != _pdata)
{
delete[]_pdata;
_pdata = NULL;
}
}
String &operator=(const String&s)
{
//检查自赋值
if (this != &s)
{
char*temp = new char[strlen(s._pdata) + ];
strcpy(temp, s._pdata);
delete[]_pdata;
_pdata = temp;
}
return *this;
}
private:
char*_pdata;
};
void main()
{
String s1 ("hello world");
String s2=s1;
}

当类里面有指针对象时,进行简单赋值的浅拷贝,两个对象指向同一块内存,存在崩溃的问题!这里我们要进行深拷贝。

  • 深拷贝
 # define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<string>
using namespace std;
class String
{
public:
String(const char* pdata)//构造函数
:_pdata(new char[strlen(pdata) + ])
{
strcpy(_pdata, pdata);
}
String(const String&s)//拷贝构造
:_pdata(new char[strlen(s._pdata) + ])
{
strcpy(_pdata, s._pdata);
}
~String()//析构函数
{
if (NULL != _pdata)
{
delete[]_pdata;
_pdata = NULL;
}
}
String &operator=(const String&s)
{
//检查自赋值
if (this != &s)
{
char*temp = new char[strlen(s._pdata) + ];
strcpy(temp, s._pdata);
delete[]_pdata;
_pdata = temp;
}
return *this;
}
private:
char*_pdata;
};
//简洁版
class String
{
public:
String(const char* pData)
: _pData(new char[strlen(pData) + ])
{
strcpy(_pData, pData);
} String(const String& s)
: _pData(NULL)
{
String temp(s._pData);
std::swap(_pData, temp._pData);
} String& operator=(const String& s)
{
if (this != &s)
{
String temp(s._pData);
std::swap(_pData, temp._pData);
}
return *this;
}
~String()
{
if (NULL != _pData)
{
delete[] _pData;
_pData = NULL;
}
}
private:
char* _pData;
};
void main()
{
String s1 ("hello world");
String s2=s1;
}

  • 写时拷贝
 #include<iostream>
#include<string.h>
#include<assert.h>
namespace COW
{
class String
{
public:
String(const char* pData)
: _pData(new char[strlen(pData) + ])
, _refCount(new int)
{
*_refCount = ;
strcpy(_pData, pData);
} // String s2(s1);
String(String& s)
: _pData(s._pData)
, _refCount(s._refCount)
{
++(*_refCount);
} // s1 = s2;
String& operator=(String s)
{
if (this != &s)
{
if (--(*_refCount) == )
{
delete[] _pData;
delete _refCount;
} _pData = s._pData;
_refCount = s._refCount;
++(*_refCount);
} return *this;
} ~String()
{
if (--(*_refCount) == )
{
delete[] _pData;
delete _refCount;
}
}
// 返回值 函数名(参数)
char& operator[](int index)
{
// 检测返回
// *_refCount > 1
// *_refCount = 1
if (*_refCount > )
{
(*_refCount)--;
String temp(_pData);
_pData = temp._pData;
_refCount = temp._refCount;
(*_refCount)++;
}
return _pData[index];
}
/*const char& operator[](int index)const
{ return _pData[index];
}*/
private:
char* _pData;
int* _refCount;
};
}
void FunTest()
{
COW::String s1("");
COW::String s2("");
const COW::String s3 = s2;
s1 = s2;
s2[] = '';
//std::cout << s3[1];
}
int main()
{
FunTest();
return ;
}
  string 之间拷贝时不是深拷贝,只拷贝了指针, 也就是共享同一个字符串内容, 只有在内容被修改的时候, 才真正分配了新的内存并 copy 。 比如 s[0]='1' 之类的修改字符串内容的一些write操作, 就会申请新的内容,和之前的共享内存独立开。 所以称之为 『copy-on-write』

浅拷贝&深拷贝&Copy On Write(Sring类)的更多相关文章

  1. [置顶] operator overloading(操作符重载,运算符重载)运算符重载,浅拷贝(logical copy) ,vs, 深拷贝(physical copy)

    operator overloading(操作符重载,运算符重载) 所谓重载就是重新赋予新的意义,之前我们已经学过函数重载,函数重载的要求是函数名相同,函数的参数列表不同(个数或者参数类型).操作符重 ...

  2. 浅拷贝(Shallow Copy) VS 深拷贝(Deep Copy)

    首先,深拷贝和浅拷贝针对的是对象类型(对象,数组,函数) 浅拷贝指的是只是拷贝了对象的引用地址,彼此之间高耦合,一个改变,另一个可能也随之改变: 深拷贝是指只是完整的将变量的值拷贝过来,是一个新的对象 ...

  3. copy&mutableCopy 浅拷贝(shallow copy)深拷贝 (deep copy)

    写在前面 其实看了这么多,总结一个结论: 拷贝的初衷的目的就是为了:修改原来的对象不能影响到拷贝出来得对象 && 修改拷贝出来的对象也不能影响到原来的对象 所以,如果原来对象就是imm ...

  4. python中赋值-浅拷贝-深拷贝之间的关系

    赋值: 变量的引用,没有拷贝空间 对象之间赋值本质上 是对象之间的引用传递而已.也就是多个对象指向同一个数据空间. 拷贝的对象分两种类型: . 拷贝可变类型 浅拷贝: 只拷贝第一层数据,不关心里面的第 ...

  5. Python__学习路上的坑之--引用,浅拷贝,深拷贝

    copy : 相当于只是拷贝表面一层,如果里面还有深层次的引用,那么也是直接拷贝引用的地址,而且如果拷贝对象是不可变类型比如元组,那么也是直接拷贝引用. deepcopy: 无论是拷贝可变类型还是不可 ...

  6. python学习笔记七:浅拷贝深拷贝

    原理 浅拷贝 import copy b = copy.copy(a) demo: >>> a=[1,['a']] >>> b=a >>> c=c ...

  7. Day 07 -02 拷贝 浅拷贝 深拷贝

    必考 存一个值还是多个值 一个值:整型/浮点型/字符串 多个值:列表/元祖/字典/集合 有序or 无序 有序:字符串/列表/元祖 无序:字典/集合 可变or 不可变 可变:列表/字典/集合 不可变:整 ...

  8. JS中有关对象的继承以及实例化、浅拷贝深拷贝的奥秘

    一.属性的归属问题 JS对象中定义的属性和方法如果不是挂在原型链上的方法和属性(直接通过如类似x的方式进行定义)都只是在该对象上,对原型链上的没有影响.对于所有实例共用的方法可直接定义在原型链上这样实 ...

  9. $.extend()浅拷贝深拷贝

    参考网址:http://bijian1013.iteye.com/blog/2255037 jQuery.extend() 函数用于将一个或多个对象的内容合并到目标对象. 注意:1. 如果只为$.ex ...

随机推荐

  1. linux服务基础之ftp服务

    ftp是一种文件传输协议,我们以redhat6.9为服务器系统,来介绍一下ftp服务器,这里我们先介绍一下ftp协议工作的原理 ftp协议可以在不同类型的计算机之间传输文件,工作流程大致为 1:客户机 ...

  2. 初学Node.js -环境搭建

    从毕业一直到现在都是在做前端,总感觉缺少点什么,java? PHP? .Net? 框架太多了,学起来不好掌握,听说node.js挺牛的,我决定把node.js好好的学一下.首先是环境的配置,这个配置真 ...

  3. css3新样式

    超出两行变省略号 overflow:hidden; text-overflow:ellipsis;display:-webkit-box; -webkit-box-orient:vertical;-w ...

  4. React学习(4)——向服务器请求数据并显示

    本文中涉及到的技术包括:node.js/express服务器的搭建.fetch发送数据请求. 在之前的几篇文章中,介绍了如何搭建基础的React项目,以及一些简单知识,现在,我们还需要掌握如何用Rea ...

  5. C#截取两个字符串间的字符串问题

    string s = "我爱北京天安门和长城"; string s1 = "北京"; string s2 = "和"; int i = s. ...

  6. 2.5 进程控制之wait函数

    一.绪论 一个进程在终止时会关闭所有文件描述符,释放在用户空间分配的内存,但它的PCB还保留着,内核在其中保存了一些信息:如果 是正常终止则保存着退出状态,如果是异常终止则保存着导致该进程终止的信号是 ...

  7. 在amazon linux上安装Jenkins

    原文请参考: https://medium.com/@itsmattburgess/installing-jenkins-on-amazon-linux-16aaa02c369c

  8. POJ-2421-Constructing Roads(最小生成树 普利姆)

    Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 26694   Accepted: 11720 Description The ...

  9. hdu1233 继续畅通工程 (最小生成树——并查集)

    还是畅通工程 Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Sub ...

  10. 【WPF】创建基于模板的WPF控件(经典)

    原文:[WPF]创建基于模板的WPF控件(经典) WPF可以创建两种控件,它们的名字也很容易让人混淆:用户控件(User Control)和定制控件(Customer Control),之所以如此命名 ...