我们可以定义拷贝操作,使类的行为看起来像一个值或者像一个指针,这取决于如何拷贝指针成员。

当我们拷贝一个像值的对象时,副本和原对象是完全独立的,改变副本不会对原对象有任何影响,反之亦然。标准库容器和string类的行为像一个值。

当我们拷贝一个行为像指针的类的对象时,副本和原对象使用相同的底层数据,改变副本也会改变原对象,反之亦然。

浅拷贝,指的是在对象复制时,只是对对象中的数据成员进行简单的赋值,默认拷贝构造函数执行的也是浅拷贝。这样一来可能出现多个指针指向同一块内存的情况

在“深拷贝”的情况下,对于对象中动态成员,就不能仅仅简单地赋值了,而应该重新动态分配空间

一、行为像值的类(不同的类对象的指针数据成员指向独立的内存空间)

class HasPtr
{
public:
HasPtr(const HasPtr&) :ps(new string(*p.ps), i(p.i)){}
HasPtr& operator=(const HasPtr &);
~HasPtr(){ delete ps; }
private:
string *ps;
int i;
};
/*
通过先拷贝右侧运算对象,我们可以处理自赋值情况,并能保证异常发生时代码安全。
注意:1、返回值 2、自赋值 3、new异常。 解决方案:返回引用,先判断是否自赋值,若是则返回,在释放旧内存前先分配好内存
*/
HasPtr& HasPtr::operator=(const HasPtr &rhs)
{
auto newp = new string(*rhs.ps);//拷贝底层string
delete ps;//释放旧内存
ps = newp;
i = rhs.i;
//处理连锁赋值
return *this;
} HasPtr& HasPtr::operator=(const HasPtr &rhs)
{
delete ps;//释放旧内存
//如果rhs和*this是同一个对象,我们就将从已释放的内存中拷贝数据
ps = new string(*rhs.ps);
i = rhs.i;
return *this;
}

二、定义行为像指针的类(多个类对象的指针指向同一个地址,但不能出现错误)

因为可能会有多个类的指针指向同一个地址,所以使用引用计数,引用计数是个指针,如果是个值得话,考虑下面情况(值得话每个对象都保存一个副本,互相独立)。

HasPtr p1("ljy");

HasPtr p2(p1);

HasPtr p3(p1);//p1,p2,p3指向相同的string,若引用计数是值的话,无法更新

class HasPtr
{
private:
string *ps;
int i;
int *use;
public:
HasPtr(const HasPtr &p) :ps(p.ps), i(p.i), use(p.use){ ++*use; }
HasPtr& operator=(const HasPtr&);
~HasPtr();
}; HasPtr::~HasPtr()
{
if (--*use == )
{
delete ps;
delete use;
}
} HasPtr& HasPtr::operator=(const HasPtr &rhs)
{
//先++rhs.use,可以处理自赋值的情况
++*rhs.use;
if (--*use == )
{
delete ps;
delete use;
}
ps = rhs.ps;
i = rhs.i;
use = rhs.use;
return *this;
}

【c++】拷贝控制具体分析的更多相关文章

  1. C++ Primer : 第十三章 : 拷贝控制之对象移动

    右值引用 所谓的右值引用就是必须将引用绑定到右值的引用,我们通过&&来绑定到右值而不是&, 右值引用只能绑定到即将销毁的对象.右值引用也是引用,因此右值引用也只不过是对象的别名 ...

  2. C++ Primer : 第十三章 : 拷贝控制之拷贝控制和资源管理

    定义行为像值的类 行为像值的类,例如标准库容器和std::string这样的类一样,类似这样的类我们可以简单的实现一个这样的类HasPtr. 在实现之前,我们需要: 定义一个拷贝构造函数,完成stri ...

  3. C++的那些事:类的拷贝控制

    1,什么是类的拷贝控制 当我们定义一个类的时候,为了让我们定义的类类型像内置类型(char,int,double等)一样好用,我们通常需要考下面几件事: Q1:用这个类的对象去初始化另一个同类型的对象 ...

  4. C++ Primer : 第十三章 : 拷贝控制之拷贝、赋值与销毁

    拷贝构造函数 一个构造函数的第一个参数是自身类类型的引用,额外的参数(如果有)都有默认值,那么这个构造函数是拷贝构造函数.拷贝构造函数的第一个参数必须是一个引用类型. 合成的拷贝构造函数   在我们没 ...

  5. Chapter13:拷贝控制

    拷贝控制操作:拷贝构造函数.拷贝赋值运算符.移动构造函数.移动赋值运算符.析构函数. 实现拷贝控制操作的最困难的地方是首先认识到什么时候需要定义这些操作. 拷贝构造函数: 如果一个构造函数的第一个参数 ...

  6. C++ 拷贝控制和资源管理,智能指针的简单实现

    C++ 关于拷贝控制和资源管理部分的笔记,并且介绍了部分C++ 智能指针的概念,然后实现了一个基于引用计数的智能指针.关于C++智能指针部分,后面会有专门的研究. 通常,管理类外资源的类必须定义拷贝控 ...

  7. c/c++ 拷贝控制 构造函数的问题

    拷贝控制 构造函数的问题 问题1:下面①处的代码注释掉后,就编译不过,为什么??? 问题2:但是把②处的也注释掉后,编译就过了,为什么??? 编译错误: 001.cpp: In copy constr ...

  8. c/c++ 拷贝控制 右值与const引用

    拷贝控制 右值与const引用 背景:当一个函数的返回值是自定义类型时,调用侧用什么类型接收?? 1,如果自定义类型的拷贝构造函数的参数用const修饰了:可以用下面的方式接收. Test t2 = ...

  9. C++ Primer 笔记——拷贝控制

    1.如果构造函数的第一个参数是自身类类型的引用,且任何额外参数都有默认值,则此构造函数是拷贝构造函数.拷贝构造函数的第一个参数必须是引用类型(否则会无限循环的调用拷贝构造函数). 2.如果没有为一个类 ...

随机推荐

  1. zabbix告警邮件、短信发送错误快速排查方法

    zabbix告警邮件.短信发送错误快速排查方法 背景 zabbix告警邮件.短信经常有同事反馈发送错误的情况,这个问题排查的角度很多,那么最快捷的角度是什么呢? 在我看来,最快的角度就是判断这个告警邮 ...

  2. 微信小程序---代码构成

    通过开发者工具快速创建了一个demo项目,观察后可以发现这个项目里边生成了不同类型的文件: .json 后缀的 JSON 配置文件 .wxml 后缀的 WXML 模板文件 .wxss 后缀的 WXSS ...

  3. hibernate5.x版本org.hibernate.MappingException: Unknown entity问题

    /* * //创建hibernate配置对象 Configuration cfg = new Configuration(); cfg.configure("hibernate.cfg.xm ...

  4. 多线程test

    import java.io.UnsupportedEncodingException; import java.util.HashMap; import java.util.Map; import ...

  5. OpenJudge-百练-2755

    这道题用递归写的话还是很好写的,我们设递归函数的名称为Ways(w,k) . 它的含义就是,w的大小,取k个物品,有多少种方式. 我们可以知道递归的边界条件就是当w的大小为0的时候,我们的方法数只有一 ...

  6. [模板] Miller-Rabin 素数测试

    细节挺多的.. #include<iostream> #include<cstdlib> #include<cstdio> #include<ctime> ...

  7. CAS机制(多线程)

    ---- 什么是CAS机制 CAS机制主要是发生于Java中原子操作类(JUC)的底层实现中,其中在CAS机制中包含3个基本参数:内存地址V.旧预期值A.要修改的新值B. 当要更新一个变量的时候,只有 ...

  8. PROPAGATION_REQUIRED,ISOLATION_DEFAULT; '',-java.lang.Exception

    转https://stackoverflow.com/questions/29117679/spring-transactional-management-propagation-required-i ...

  9. 《C/C++工程师综合练习卷》

    前言 前天拿这个<C/C++工程师综合练习卷>练习了一下,现将错题以及精题分析总结. 错题分析与总结 2 . 下面的程序可以从1-.n中随机等概率的输出m个不重复的数.这里我们假设n远大于 ...

  10. 基于 NodeJs 打造 Web 在线聊天室

    Socket.IO 简介与基础环境搭建 任务时间:10min ~ 20min 关于 Socket.IO Socket.IO 可以实现在浏览器和服务器之间实时双向通信,本节课程将详细介绍 Socket. ...