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. nodejs--http

    http模块主要用到四个方法: 1.Server类 const http = require('http'); let server = new Server(); server.on('reques ...

  2. Windows下安装Mysql5.5.27(社区版)

    所有平台的 MySQL 下载地址为: MySQL 下载. 挑选你需要的 MySQL Community Server 版本及对应的平台. 运行mysql-5.5.27-win32.msi 进入欢迎界面 ...

  3. Solr简单总结

    Solr 运行Solr服务 方式一:Jetty服务器启动Solr 进入solr-4.10.2/example目录 打开命令行,执行java –jar start.jar命令,即可启动Solr服务 打开 ...

  4. 二、Django需要的知识点

    1.请求(request): 客户端到服务器端. 响应(response):服务器端到客户端. HTTP/1.1 协议共定义了 8 种请求方式,分别是: OPTIONS. HEAD. GET. POS ...

  5. 生产Web架构优化方案(动态转静态)

    Infi-chu: http://www.cnblogs.com/Infi-chu/ 一.门户新闻业务: 1. 特点:网页一旦发布,再次改动网页内容的几率很低,新闻业务内容的静态化相对比较简单 2. ...

  6. (原创)用Verilog实现一个参数化的呼吸灯(Verilog,CPLD/FPGA)

    1.Abstract     观察到一个有趣的现象,每当把Apple笔记本合上的时候,那个白色的呼吸灯就会反复地由暗渐明,然后又由明渐暗,乍一看就像Apple笔记本在打盹休息一样,十分可爱!于是突发奇 ...

  7. 初步学习pg_control文件之十二

    接前问,初步学习pg_control文件之十一,再来看下面这个 XLogRecPtr minRecoveryPoint; 看其注释: * minRecoveryPoint is updated to ...

  8. [Python 3.X]python练习笔记[2]-----用python实现七段数码管显示年月日

    #SevenDigitsDrawV2.py import turtle import time def drawGap(i):#绘制数码管间隔 turtle.penup() turtle.fd(i) ...

  9. python中的os,shutil模块的定义以及用法

    # os 模块 os.sep 可以取代操作系统特定的路径分隔符.windows下为 '\\' os.name 字符串指示你正在使用的平台.比如对于Windows,它是'nt',而对于Linux/Uni ...

  10. 58HouseSearch项目迁移到asp.net core

    前言 58HouseSearch这个项目原本是基于ASP.NET MVC 4写的,开发环境是Windows+VS2015,发布平台是linux+mono+jexus,这样看来整个项目基本已经满足跨平台 ...