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. MySQL中Date,DateTime,TimeStamp和Time的比较

    名称 显示格式 显示范围 应用场景 后台取值 Date YYYY-MM-DD 1601-01-01 到 9999-01-01 当业务需求中只需要精确到天时, 可以用这个时间格式 @JSONField( ...

  2. Spring Boot2.0拦截器简单实现判断是否登录

    在进行项目开发的时候使用springboot框架用到拦截器时发现2.0以后原来的抽象类WebMvcConfigurerAdapter已经过时了,去官网查文档2.x版本要实现拦截器功能改为需要继承Web ...

  3. vue入门笔记

    Vue (读音 /vjuː/,类似于 view) 是一套用于构建用户界面的渐进式框架.与其它大型框架不同的是,Vue 被设计为可以自底向上逐层应用.Vue 的核心库只关注视图层,不仅易于上手,还便于与 ...

  4. PHP如何实现99乘法表?

    看到这个问题,可能大家更多的是考虑到用for循环,个人觉得使用for循环太影响程序性能.推荐使用递归处理.  /** * Title : 递归实现99乘法表 * Author : Bruceqi * ...

  5. ubuntu如何设置Python的版本

    Ubuntu默认已经安装了Python的版本了,不过是Python2的版本. 我们安装好Python3想把他切换为系统默认的版本. sudo update-alternatives --config ...

  6. WordPress博客插件程序:搜索下拉框openSug

    百度搜索框下拉提示Wordpress组插件. 下载地址:https://www.opensug.org/faq/wp-content/uploads/2018/12/opensug.wordpress ...

  7. Angular2中使用Jsonp

    除了引入HttpModule模块,还要引入 JsonpModule 模块 import { HttpModule, JsonpModule } from '@angular/http'; Observ ...

  8. 码云配置webhooks自动触发拉取代码

    webhooks的使用 码云和github的钩子叫webhooks 每次您 push 代码后,都会给远程 HTTP URL 发送一个 POST 请求 码云项目管理页面的webhooks设置: http ...

  9. PAT (Basic Level) Practice (中文)1002

    1002 写出这个数 (20 分) 读入一个正整数 n,计算其各位数字之和,用汉语拼音写出和的每一位数字. 输入格式: 每个测试输入包含 1 个测试用例,即给出自然数 n 的值.这里保证 n 小于 1 ...

  10. 1.使用pycharm搭建开发调试环境【转】

    感谢 feigamesnb 第一步:安装python2.7环境 去https://www.python.org/downloads/下载windows版本的python,选择2.7版本,按提示安装,并 ...