拷贝构造、赋值构造、深拷贝、浅拷贝、位拷贝、值拷贝
2015-11-26 14:21
357 查看
很早之前,一直对这些名词很不解,翻看了c++ primer很多次,也只知道其用法,不知其解。说白了,就是不知道为什么有这些各式的拷贝的存在,或者是说在何种环境下面要使用得上!今天无意翻到当初写的小例子,重新整理后帖上来作个记号!
//=================================
一,在什么环境下面可能需要使用自定义拷贝、赋值构造?
在解释这些名词之前,需要知道一点,在什么环境下面需要使用自定义拷贝、赋值构造,答案就是:当一个自定义的struct或class中包括有指针对象时(可能是堆栈资源或是文件等等,以前总以为只是普通指针),拷贝构造和赋值构造就可能需要自定义(是否重定义取决于类的实现模型是否需要,以前总以为是必须要实现),因为你需要明确的定义当class发生拷贝或赋值构造时,class中的那些指针对象所指向的资源也是否需要COPY一个副本(重新分配堆栈)。当没有自定义构造函数时,系统的默认拷贝和赋值构造函数只对指针进行位拷贝,即只对二个class中的指针进行”=”赋值,指针所指向的的堆栈资源仍然是一样的,这时就会发生二种情况:一, 其中一个类中指针对象被析构时,虽一个类的指针便会成野指针,调用时程序异常或崩溃;二,当二个类都析构时,二个指针对象所指向的堆栈会被delete二次,造成内存泄露。可是,可是也不是所有的指针对象在发生拷贝构造时都需要重新分配堆栈,请参第五条!
//=================================
二,名词解释:
拷贝构造、赋值构造:
拷贝构造:复制构造函数是一种特殊构造函数,具有单个形参,该形参(常用 const 修饰)是对该类类型的引用。当定义一个新对象并用一个同类型的对象对它进行初始化时,将显式使用复制构造函数。当将该类型的对象传递给函数或函数返回该类型的对象时,将隐式使用复制构造函数。(c++ primer原话)
赋值构造:与复制构造的行为一样,只是通过重载“=”,通过=来将目标初始化自己。虽然行为一样,但实现时有区别,需要排除是否是 “自己=自己”, 是否有“先前的指针对象没有delete”的情况!
浅拷贝(位拷贝)、深拷贝(值拷贝):
浅拷贝:当发生拷贝或赋值构造时,系统将依次调用目标类的每一个成员变量的操作符“=”来初始化自己类的成员变量; 但二个class中都有指针对象时,二个指针进行”=”操作时,指针的值将是一样的(指向的堆栈是一样的)。
反之深拷贝:行为跟浅拷贝一样,只是针对指针对象时,被构造的类会先将为自己的针对对象分配新的堆栈,然后再将目标类中的指针所指向的堆栈进行memcpy。
三,=================================
demo:
//=================================
四,何时会发生拷贝构造?
以下情况都会调用拷贝构造函数:
(1)一个对象以值传递的方式传入函数体
(2)一个对象以值传递的方式从函数返回
(3)一个对象需要通过另外一个对象进行初始化。
//=================================
五,在什么环境下面可能需要使用浅拷贝、深拷贝?
无论深浅,都是需要的。当深拷贝发生时,通常表明存在着一个“聚合或组合的关系“,而浅拷贝发生时,通常表明存在着一个弱的“关联关系”。
二种情况:
1,指针成员对象是class的成员变量,指针的堆栈和生命周期都是由class自己来维护和管理,那么,当拷贝发生时,需要自定义拷贝、赋值构造函数,对指针指向的资源进行深拷贝。
2,指针成员对象是class的成员变量,但堆栈的申请和生命周期由其它类来维护和管理,那么,这个类发生拷贝时,只能进行浅拷贝。
//=================================
一,在什么环境下面可能需要使用自定义拷贝、赋值构造?
在解释这些名词之前,需要知道一点,在什么环境下面需要使用自定义拷贝、赋值构造,答案就是:当一个自定义的struct或class中包括有指针对象时(可能是堆栈资源或是文件等等,以前总以为只是普通指针),拷贝构造和赋值构造就可能需要自定义(是否重定义取决于类的实现模型是否需要,以前总以为是必须要实现),因为你需要明确的定义当class发生拷贝或赋值构造时,class中的那些指针对象所指向的资源也是否需要COPY一个副本(重新分配堆栈)。当没有自定义构造函数时,系统的默认拷贝和赋值构造函数只对指针进行位拷贝,即只对二个class中的指针进行”=”赋值,指针所指向的的堆栈资源仍然是一样的,这时就会发生二种情况:一, 其中一个类中指针对象被析构时,虽一个类的指针便会成野指针,调用时程序异常或崩溃;二,当二个类都析构时,二个指针对象所指向的堆栈会被delete二次,造成内存泄露。可是,可是也不是所有的指针对象在发生拷贝构造时都需要重新分配堆栈,请参第五条!
//=================================
二,名词解释:
拷贝构造、赋值构造:
拷贝构造:复制构造函数是一种特殊构造函数,具有单个形参,该形参(常用 const 修饰)是对该类类型的引用。当定义一个新对象并用一个同类型的对象对它进行初始化时,将显式使用复制构造函数。当将该类型的对象传递给函数或函数返回该类型的对象时,将隐式使用复制构造函数。(c++ primer原话)
赋值构造:与复制构造的行为一样,只是通过重载“=”,通过=来将目标初始化自己。虽然行为一样,但实现时有区别,需要排除是否是 “自己=自己”, 是否有“先前的指针对象没有delete”的情况!
浅拷贝(位拷贝)、深拷贝(值拷贝):
浅拷贝:当发生拷贝或赋值构造时,系统将依次调用目标类的每一个成员变量的操作符“=”来初始化自己类的成员变量; 但二个class中都有指针对象时,二个指针进行”=”操作时,指针的值将是一样的(指向的堆栈是一样的)。
反之深拷贝:行为跟浅拷贝一样,只是针对指针对象时,被构造的类会先将为自己的针对对象分配新的堆栈,然后再将目标类中的指针所指向的堆栈进行memcpy。
三,=================================
demo:
class CFoo { public: CFoo() :m_pStr( NULL ) { } CFoo( const CFoo& rhs ) { m_pStr = new std::string; *m_pStr = *rhs.m_pStr; } void init( const std::string &str ) { if ( !m_pStr ) { m_pStr = new std::string; *m_pStr = str; } } CFoo& operator=( const CFoo& rhs ) { if ( this == &rhs ) // 判断是否是自己给自己赋值 return *this; if ( m_pStr ) // 判断是不是已经申请过堆栈的指针,没有这一步,会导致已申请过的堆栈没有进行delete导致的内存泄露 { delete m_pStr; m_pStr = NULL; } m_pStr = new std::string; *m_pStr = *rhs.m_pStr; return *this; } ~CFoo() { if ( m_pStr ) { delete m_pStr; m_pStr = NULL; } } void printSth() { if ( m_pStr ) { std::cout << " this: " << this << " , m_pStr addrs: " << m_pStr << " , m_pStr value: " << *m_pStr << std::endl; } else { std::cout << " this: " << this << " , m_pStr is NULL " << std::endl; } } private: std::string *m_pStr; }; int _tmain(int argc, _TCHAR* argv[]) { ///////////////////////////////////////////////////// // [ 拷贝构造和赋值 ] CFoo foo; foo.init( "test!!!"); foo.printSth(); CFoo foo2( foo ); // 拷贝构造 foo2.printSth(); CFoo foo3 = foo; // 这里并不是赋值,而是拷贝构造 foo3.printSth(); CFoo foo4; foo4.printSth(); foo4 = foo; // 这里才是赋值构造 foo4.printSth(); ////////////////////////////////////////////////////// return 0; }
//=================================
四,何时会发生拷贝构造?
以下情况都会调用拷贝构造函数:
(1)一个对象以值传递的方式传入函数体
(2)一个对象以值传递的方式从函数返回
(3)一个对象需要通过另外一个对象进行初始化。
//=================================
五,在什么环境下面可能需要使用浅拷贝、深拷贝?
无论深浅,都是需要的。当深拷贝发生时,通常表明存在着一个“聚合或组合的关系“,而浅拷贝发生时,通常表明存在着一个弱的“关联关系”。
二种情况:
1,指针成员对象是class的成员变量,指针的堆栈和生命周期都是由class自己来维护和管理,那么,当拷贝发生时,需要自定义拷贝、赋值构造函数,对指针指向的资源进行深拷贝。
2,指针成员对象是class的成员变量,但堆栈的申请和生命周期由其它类来维护和管理,那么,这个类发生拷贝时,只能进行浅拷贝。
相关文章推荐
- IOS,objective_C中用@interface和 @property 方式声明变量的区别
- ObjectiveC中的block用法解析
- C++字典树
- 协议和代理
- 中文分词:全切分分词学习
- 类的静态成员函数相关
- inline-block容器的高度撑开位置
- ucosii源码分析
- Git的安装与环境变量配置
- CSS基础知识真难啊-浮动
- dmg文件转iso格式
- 通信录分组并且分组标签悬停划入划出(包含错误信息及修改)--第三方开源--PinnedSectionListView
- 如何搭建基于Jesery框架的Restful服务
- Kafka剖析(一):Kafka背景及架构介绍
- 对话框 ~ 更新菜单和工具栏
- 黑马程序员---Java基础篇之JDK的安装和介绍
- ProgressBar,双向进度
- 选择排序
- 机器学习实战python版决策树以及Matplotlib注解绘制决策树
- STM32独立看门狗与窗口看门狗