热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

对象拷贝知识点

《cprimer》13.1章节《c程序设计语言第四版》17.5.1章节1、拷贝操作有两种:拷贝构造函数:A(constA&)。初始化一片未经初始化

《c++ primer》13.1章节

《c++程序设计语言 第四版》17.5.1章节

1、拷贝操作有两种:

  • 拷贝构造函数:A(const A&)。初始化一片未经初始化的内存
  • 拷贝赋值运算符:A& operator=(const A&)。处理的目标对象已构造且可能拥有资源的情况

2、拷贝初始化:定义变量时拷贝其他对象的值来给对象初始化,在以下情况发生:

  • 用 = 定义变量时
  • 将对象作为实参传递给非引用类型的形参时
  • 从返回类型为非引用类型的函数返回对象时
  • 用{}列表初始化数组中的元素或聚合类中的元素时
  • 向容器中插入对象时(insert()和push()会拷贝对象)

3、拷贝构造函数必须使用引用的形式,原因是根据上面第2点,如果使用传值的方式,那么会触发拷贝初始化,即会调用拷贝构造函数,也就是当你要调用拷贝构造函数的时候的过程中会再次调用拷贝构造函数。这样无限套娃。

4、深拷贝和浅拷贝

深拷贝是指进行拷贝操作之后两个对象是相互独立的,浅拷贝相反,操作一个对象会改变另一个对象的状态:

#define debug qDebug()<<
class ceshi
{
public:ceshi(int * p &#61; nullptr){this->p &#61; p;}~ceshi(){if(p)delete p;}ceshi(const ceshi &c){this->p &#61; c.p;}void debugValue(){if(p)debug *p;}void changeValue(int value){if(p)*p &#61; std::move(value);}
private:int * p{nullptr};
};int main(int argc, char *argv[])
{ceshi c1{new int(888)};ceshi c2{c1};c1.debugValue();c2.debugValue();c2.changeValue(444);c1.debugValue();c2.debugValue();
}

以上就是浅拷贝&#xff0c;拷贝时只拷贝指针的值&#xff0c;未拷贝指针指向的对象&#xff0c;当修改一个对象的状态时另一个的状态跟着变化。

这样的拷贝是深拷贝&#xff1a;

ceshi(const ceshi &c){if(c.p){this->p &#61; new int(*c.p);}else{this->p &#61; nullptr;}}

5、写前拷贝

写前拷贝就是拷贝使用浅拷贝&#xff0c;当要修改的时候再进行复制资源的操作&#xff1a;

#define debug qDebug()<<
class ceshi
{
public:ceshi(int * p &#61; nullptr){this->p &#61; p;}~ceshi(){if(p)delete p;}ceshi(const ceshi &c){this->p &#61; c.p;isShare &#61; true;}void debugValue(){if(p)debug *p;}void changeValue(int value){if(isShare){clone();isShare &#61; false;}if(p){*p &#61; std::move(value);}}
private:int * p{nullptr};bool isShare;//是否正在和其他对象共享资源void clone(){if(isShare){if(p){p &#61; new int(*p);}}}
};int main(int argc, char *argv[])
{ceshi c1{new int(888)};ceshi c2{c1};c1.debugValue();c2.debugValue();c2.changeValue(444);c1.debugValue();c2.debugValue();
}

这里增加一个变量isShare&#xff0c;标识当前对象是否在和其他对象共享资源&#xff0c;拷贝后设为true&#xff0c;当改变值时调用clone()函数复制资源。

6、拷贝与切片

#define debug qDebug()<<
class A
{
public:A(int a &#61; 444){this->a &#61; a;}A(const A & obj){this->a &#61; obj.a;debug "调用A拷贝";}
private:int a;
};class B : public A
{
public:B(int b &#61; 555){this->b &#61; b;}B(const B & obj){this->b &#61; obj.b;}
private:int b;
};int main(int argc, char *argv[])
{B objB{888};A objA &#61; objB;
}

这里基类对象等于子类对象会调用基类的拷贝构造函数&#xff0c;得到的结果是一个基类对象&#xff0c;导致子类中的成员b丢失。这种现象操作切片&#xff0c;要禁止这类操作可以&#xff1a;

  • 禁止基类拷贝&#xff1a;A(const A & obj) &#61; delete;
  • 不使用共有继承&#xff1a;class B : public A&#xff0c;改成private或protected

推荐阅读
  • Java容器中的compareto方法排序原理解析
    本文从源码解析Java容器中的compareto方法的排序原理,讲解了在使用数组存储数据时的限制以及存储效率的问题。同时提到了Redis的五大数据结构和list、set等知识点,回忆了作者大学时代的Java学习经历。文章以作者做的思维导图作为目录,展示了整个讲解过程。 ... [详细]
  • 本文讨论了使用差分约束系统求解House Man跳跃问题的思路与方法。给定一组不同高度,要求从最低点跳跃到最高点,每次跳跃的距离不超过D,并且不能改变给定的顺序。通过建立差分约束系统,将问题转化为图的建立和查询距离的问题。文章详细介绍了建立约束条件的方法,并使用SPFA算法判环并输出结果。同时还讨论了建边方向和跳跃顺序的关系。 ... [详细]
  • 本文讨论了clone的fork与pthread_create创建线程的不同之处。进程是一个指令执行流及其执行环境,其执行环境是一个系统资源的集合。在调用系统调用fork创建一个进程时,子进程只是完全复制父进程的资源,这样得到的子进程独立于父进程,具有良好的并发性。但是二者之间的通讯需要通过专门的通讯机制,另外通过fork创建子进程系统开销很大。因此,在某些情况下,使用clone或pthread_create创建线程可能更加高效。 ... [详细]
  • STL迭代器的种类及其功能介绍
    本文介绍了标准模板库(STL)定义的五种迭代器的种类和功能。通过图表展示了这几种迭代器之间的关系,并详细描述了各个迭代器的功能和使用方法。其中,输入迭代器用于从容器中读取元素,输出迭代器用于向容器中写入元素,正向迭代器是输入迭代器和输出迭代器的组合。本文的目的是帮助读者更好地理解STL迭代器的使用方法和特点。 ... [详细]
  • 本文介绍了一道经典的状态压缩题目——关灯问题2,并提供了解决该问题的算法思路。通过使用二进制表示灯的状态,并枚举所有可能的状态,可以求解出最少按按钮的次数,从而将所有灯关掉。本文还对状压和位运算进行了解释,并指出了该方法的适用性和局限性。 ... [详细]
  • 电话号码的字母组合解题思路和代码示例
    本文介绍了力扣题目《电话号码的字母组合》的解题思路和代码示例。通过使用哈希表和递归求解的方法,可以将给定的电话号码转换为对应的字母组合。详细的解题思路和代码示例可以帮助读者更好地理解和实现该题目。 ... [详细]
  • Iamtryingtomakeaclassthatwillreadatextfileofnamesintoanarray,thenreturnthatarra ... [详细]
  • Commit1ced2a7433ea8937a1b260ea65d708f32ca7c95eintroduceda+Clonetraitboundtom ... [详细]
  • 本文介绍了如何在给定的有序字符序列中插入新字符,并保持序列的有序性。通过示例代码演示了插入过程,以及插入后的字符序列。 ... [详细]
  • HDFS2.x新特性
    一、集群间数据拷贝scp实现两个远程主机之间的文件复制scp-rhello.txtroothadoop103:useratguiguhello.txt推pushscp-rr ... [详细]
  • 李逍遥寻找仙药的迷阵之旅
    本文讲述了少年李逍遥为了救治婶婶的病情,前往仙灵岛寻找仙药的故事。他需要穿越一个由M×N个方格组成的迷阵,有些方格内有怪物,有些方格是安全的。李逍遥需要避开有怪物的方格,并经过最少的方格,找到仙药。在寻找的过程中,他还会遇到神秘人物。本文提供了一个迷阵样例及李逍遥找到仙药的路线。 ... [详细]
  • iOS Swift中如何实现自动登录?
    本文介绍了在iOS Swift中如何实现自动登录的方法,包括使用故事板、SWRevealViewController等技术,以及解决用户注销后重新登录自动跳转到主页的问题。 ... [详细]
  • Spring常用注解(绝对经典),全靠这份Java知识点PDF大全
    本文介绍了Spring常用注解和注入bean的注解,包括@Bean、@Autowired、@Inject等,同时提供了一个Java知识点PDF大全的资源链接。其中详细介绍了ColorFactoryBean的使用,以及@Autowired和@Inject的区别和用法。此外,还提到了@Required属性的配置和使用。 ... [详细]
  • 模板引擎StringTemplate的使用方法和特点
    本文介绍了模板引擎StringTemplate的使用方法和特点,包括强制Model和View的分离、Lazy-Evaluation、Recursive enable等。同时,还介绍了StringTemplate语法中的属性和普通字符的使用方法,并提供了向模板填充属性的示例代码。 ... [详细]
  • C++语言入门:数组的基本知识和应用领域
    本文介绍了C++语言的基本知识和应用领域,包括C++语言与Python语言的区别、C++语言的结构化特点、关键字和控制语句的使用、运算符的种类和表达式的灵活性、各种数据类型的运算以及指针概念的引入。同时,还探讨了C++语言在代码效率方面的优势和与汇编语言的比较。对于想要学习C++语言的初学者来说,本文提供了一个简洁而全面的入门指南。 ... [详细]
author-avatar
曦雯天使
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有