构造函数_析构函数_深拷贝与浅拷贝
拷贝构造函数为什么要使用引用而不是值传递???
CExample aaa(2);
CExample bbb(3);
assignment operator // bbb = aaa;
copy constructor // CExample ccc = aaa;
bbb对象已经实例化了,不需要构造,此时只是将aaa赋值给bbb,只会调用赋值函数opetator=;
但是ccc还没有实例化,因此调用的是拷贝构造函数,构造出ccc,而不是赋值函数.
构造ccc,实质上是ccc.CExample(aaa); 我们假如拷贝构造函数参数不是引用类型的话, 那么将使得 ccc.CExample(aaa)变成aaa传值给ccc.CExample(CExample ex),即CExample ex = aaa,因为 ex 没有被初始化, 所以 CExample ex = aaa 继续调用拷贝构造函数,接下来的是构造ex,也就是 ex.CExample(aaa),必然又会有aaa传给CExample(CExample ex), 即 CExample ex = aaa;那么又会触发拷贝构造函数,就这下永远的递归下去......
C++提供构造函数和析构函数用于 数据成员的初始化和清理。
构造函数:
定义:
1、C++定义与类名相同的特殊成员函数,即构造函数。
2、有参或无参。
3、无返回类型。
调用:
自动调用,C++编译器会自动调用构造函数;
手动调用:在一些情况需要手动调用。
先后定义两个对象T1和T2,构造函数先调用T1后调用T2,析构函数倒序调用,先调用T2后调用T1。
无参构造函数:
在类外定义对象后,自动调用无参构造函数,并在内部进行对象数据成员的赋值;
有参构造函数:
括号法:Text T1(3,4);
等号法:Text T2 = (1,2,3,4); //逗号表达式将最右边的数字返回。一个参数
手动调用:Text T3 = T1(3,4); //对象的初始化,调用拷贝构造函数
Text T4 ; T4 = T3; //对象的赋值 调用的是C++自带的 operator = () 或者用户重载的等号操作函数。
重要:对象的初始化 与 对象的赋值 是不同的概念。C++编译器分别调用的是拷贝构造函数和等号操作符。
拷贝(copy)构造函数:用1个对象去初始化另一个对象 :
1、Text T2 = T1; //注意对象初始化使用的是拷贝构造函数
2、Text T2(T1);
3、 调用f(T2)时,C++编译器调用拷贝构造函数,用T2完成p的初始化。此时,p是一个与T2等价的元素(非指针,非引用),f()函数结束,元素p被析构。
void f(Text p) {cout << p.fun() << endl; }
4、函数的返回值是一个元素,返回的是一个匿名对象,所以C++编译器会调用匿名对象类的拷贝构造函数
void display() {g(); //析构A后,匿名对象未使用,匿名对象析构。// Text m = g(); 匿名对象初始化一个同类型的对象,匿名对象转成有名对象,不调用匿名对象的析构函数。而是在display()函数结束析构m时调用m的析构函数// Text n(1,2);// n = g(); 匿名对象 赋值 给另外一个同类型的对象,先调用 operator=()操作符,然后匿名对象被析构。函数结束后,析构n} Text g() {Text A(1,2); //调用有参构造函数return A; //先调用拷贝构造函数,创建一个匿名对象。同时A被析构(c++调用一次析构函数)。 }
构造函数调用规则研究:
在定义类时,没有写构造函数,C++编译器会提供一个默认构造函数。
写了构造函数就必须要使用它。
浅拷贝问题:(自己编写拷贝构造函数即可:主要针对有指针成员)
1、拷贝构造函数
Text obj2 = obj1; //调用obj2的拷贝构造函数 Text(Text& zty) {}
如果Text里面有两个变量,其中一个为指针。
char* p;
int len;
如果没有定义拷贝构造函数,就会调用C++自带的拷贝构造函数,这个时候:
obj1的成员变量p和len都在栈区,p指针存放的是地址信息,指向堆中的数据(全局变量区复制过来的,注意:全局变量区和堆区都有这部分数据)
C++自带的拷贝构造函数,执行了浅拷贝,只是在栈区把p和len复制了一份给obj2,故p也指向堆中的数据区域。在两个变量生命周期结束,需要析构时,obj2正常析构,数据析构,指针复NULL,obj1中的p就变成了野指针。
2、等号操作符
Text obj1("sf");
Text obj2("safdsg"); //调用类中的有参构造函数
obj2 = obj1; //如果不自己重载operator=(),则调用C++自己的=操作符进行p和len简单的值拷贝,指针所指的堆中区域没有拷贝,obj1和obj2中的指针p都指向堆中相同区域的数据。
构造函数的初始化列表:
解决了在B类中组合了一个A类对象的(其中,A类设计了构造函数)
根据构造函数的调用规则,设计A的构造函数,必学要用,在B中没有机会初始化A
新的语法:
class A { public: A(int _a){a = _a;}~A() {} private:int a; } class B { public:B::B(int _b1):a2(2),a3(3) {b1 = _b1;} B::B(int _b1, int v2, int v3):a2(v2),a3(v3) {b1 = _b1; } private:int b1;A a2;A a3; } void main() {B zty(1);B lunais(1,2,3); }
// 先执行被组合对象的构造函数A,按照定义顺序,而不按照初始化列表顺序。析构函数相反。
如果类中有const对象,必须用初始化列表进行赋初值
class B {public:B::B(int _b1):a2(2),a3(3),c(20) {b1 = _b1;} B::B(int _b1, int v2, int v3):a2(v2),a3(v3),c(20) //c也可以赋值为其他值 {b1 = _b1; } private:const int c;int b1;A a2;A a3; }
拷贝构造函数深拷贝栗子:
浅拷贝只是在栈区将指针内保存的地址复制了一份,而没有将堆中的数据复制一份;
深拷贝需要申请新的内存区域,并将数据复制一份。
Array(const Array& obj) {this->_array = new int[this->_length];for( int i = 0; i < _length; ++i){this->_array[i] = obj._array[i]; //数组 int* _array; } }
转载于:https://www.cnblogs.com/Lunais/p/5668226.html
构造函数_析构函数_深拷贝与浅拷贝相关推荐
- 【黑马程序员 C++教程从0到1入门编程】【笔记4】C++核心编程(类和对象——封装、权限、对象的初始化和清理、构造函数、析构函数、深拷贝、浅拷贝、初始化列表、友元friend、运算符重载)
黑马程序员C++教程 文章目录 4 类和对象(类属性[成员属性],类函数[成员函数]) 4.1 封装 4.1.1 封装的意义(三种权限:public公共.protected保护.private私有)( ...
- C++文件头,命名空间,new和delete,内联函数,引用,函数重载,构造函数和析构函数,深拷贝和浅拷贝,explict,this指针
目 录 1 开始学习C++............................................................................... ...
- 构造函数与析构函数的重载及浅拷贝和深拷贝
构造函数可以重载,析构函数不可以重载. 因为构造函数可以有多个且可以带参数,析构函数只有一个且不能带参数. 转自:http://blog.csdn.net/feitianxuxue/article/d ...
- vue对象深拷贝_浅谈深拷贝和浅拷贝
深拷贝和浅拷贝 说起深拷贝和浅拷贝,首先我们来看两个栗子 // 栗子1 var a = 1,b=a; console.log(a); console.log(b) b = 2; console.log ...
- C++拷贝构造函数:深拷贝和浅拷贝
1 拷贝构造函数 它是一种特殊的构造函数,由编译器调用来完成一些基于同一类的其他对象的构件及初始化. 1.1 拷贝函数的调用场景: 1.值传递传递函数体 2.值传递从函数体返回(返回匿名对象) 3.用 ...
- C++:构造函数以及析构函数
构造函数以及析构函数 对象初始化和清理 构造函数以及析构函数 构造函数的分类 括号法 显示法 隐式转换法 匿名对象 拷贝构造函数的调用时机 构造函数的调用规则 深拷贝和浅拷贝 初始化列表 类对象作为类 ...
- C++类和对象成员函数,静态成员,构造函数和析构函数、初始化列表
类和对象 数据成员的访问 定义成员函数 调用成员函数 私有成员函数 构造函数和析构函数 构造函数成员初始化列表 在构造函数中使用new的注意事项 this指针 const成员函数 运算符重载 友元函数 ...
- 构造函数和析构函数深拷贝和浅拷贝
在C++中能够定义和使用和类名相同的成员函数,这种和类名相同的成员函数叫做构造函数 构造函数可以有参数还可以没有参数 构造函数没有返回类型的声明 一般情况下C++编译器会自动调用构造函数 当然也可以手 ...
- assign深拷贝_前端深拷贝和浅拷贝
在前端攻城狮的工作实际应用中,有很多情况下在处理数据的时候,会用到数据的深拷贝和浅拷贝 例如:vue中数据是双向绑定的,页面显示依赖于从后台获取到的数据,但要将这个数据当做参数发送给另外一个接口的时候 ...
最新文章
- python的源代码文件的扩展名是-python源文件后缀是什么
- 【django】HttpResponse对象
- Vim取消查找后的高亮提示,:nohl或者:noh什么的都不管用,来一个简单粗暴方法
- C++counting sort计数排序的实现算法(附完整源码)
- Vue2.0使用嵌套路由实现页面内容切换/公用一级菜单控制页面内容切换
- Unknown custom element: xxx
- who|sort实现
- contos的apt-get安装
- u-boot移植随笔:u-boot启动流程简图
- 最大团问题-分支限界
- Mysql常用的几种join连接方式
- 解决cef加载flash时弹出黑框的问题
- 十大排序算法——选择排序法
- 某验四代消消乐 js逆向
- 只需10行代码就让你的U盘变成纯净版winPE系统安装启动盘
- oracle删除表空间和修改索引表空间
- 悲:又有华为员工猝死,原因调查中
- 小程序中集成赞赏功能
- 机器学习之金融信贷风控(一)互联网金融业申请评分卡的介绍
- 技术大佬都在看的几个公众号
热门文章
- 计算机网络—UDP协议
- 计算机组成原理—cpu于主存的连接(例题)
- upper_bound( )和lower_bound()的用法
- 2018ACM上海大都会赛: I. Matrix Game(最小费用最大流)
- bzoj 1786 bzoj 1831: [Ahoi2008]Pair 配对(DP)
- bzoj 1661: [Usaco2006 Nov]Big Square 巨大正方形(枚举)
- python库skimage 图像直方图局部均衡化
- 解决 adobe reader 只能翻页,不能滚动的问题
- java获取屏幕截图
- LaTex使用Excel实现快速插入表格