本文主要是介绍C++类和对象(HM),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
目录
1.拷贝构造函数的调用时机
2.拷贝构造函数的调用规则
3.浅拷贝和深拷贝
(1)浅拷贝
(2)深拷贝
4.初始化列表
5.类作为成员变量
1.拷贝构造函数的调用时机
我们首先要自己定义一个类:
(1)使用已知的对象初始化一个新的对象
这个相当于让已知的对象p1初始化对象p2;
(2)值传递的方式给函数的参数传值
通过打印的结果就可以发现执行了拷贝构造函数,这个是因为我们使用了值传递的方式传递对象p,实际上这两个函数里面的p并不是同一个p,编译器在调用func函数的时候会重新的拷贝一份作为副本;就是说test函数不会直接把自己的p传到func函数里面去,而是重新拷贝一份传给func函数
(3)值的方式返回局部的对象:
这个地方先调用test函数,test函数里面接着调用func函数,func函数会返回一个对象,这个对象就不会直接地返回到我们的test函数里面去 ,而是拷贝一份返回到test函数里面去,我们打印这两个对象的地址就可以发现是不一样的,这个也可以验证拷贝函数是执行了的。
2.拷贝构造函数的调用规则
(1)首先我们必须要知道的是:当我们定义了一个类以后,编译器会自动地实现至少3个函数,一个是默认的构造函数,一个是默认的析构函数,一个是拷贝构造函数(值传递);
(2)当我们自己写了一个自定义的构造函数并且使用的话,如果我们自己不写默认的构造函数,编译其实不会提供的;
(3)当我们写了拷贝构造函数但是不写默认构造函数和自定义构造函数的时候,编译器也不会提供自定义构造和默认构造函数的;
3.浅拷贝和深拷贝
(1)浅拷贝
使用编译器提供的拷贝构造函数,就是浅拷贝:
我们是使用了new在堆区上面开辟空间,把地址传递给了height指针;最后判断是否为空,不是空的话我们就释放掉,然后进行置为空指针;
因为释放是发生在程序销毁的时候,所以我们在析构的那个函数里面释放空间,但是因为定义的对象,先进去的后出来,也就是说先定义的对象后释放,所以p2先执行析构函数,释放空间,这个时候执行了堆区的空间的销毁,p1在执行析构函数,再次释放,就造成了一块空间多次释放,这个就是内存泄漏,导致程序崩溃;
浅拷贝带来的问题就是堆区空间重复释放;
(2)深拷贝
我们在原来的代码的基础上面,添加上我们自己的拷贝构造函数:
person(const person& p)
{cout << "拷贝构造函数执行中" << endl;age = p.age;//height = p.height;//这行代码是编译器默认实现的拷贝函数height = new int(*p.height);
}
原来的height = p.height;相当于是把p1的height的地址传递给了p2,这样两个就指向了同样的内存空间,所以会出现交叉多次释放的问题;
我们的解决方案就是重新开辟空间,这样p2的height就会指向新的空间(而不是原来的0x00ff48了);
这样在析构函数执行的时候,p1释放p1的空间,p2释放p2的空间,就不会出现多次释放同一块空间的问题了;----------------------这就是深拷贝。
4.初始化列表
就是提供了一种新的初始化的方法:我们原来是使用这种自定义的构造函数进行初始化:
我们现在使用的是初始化列表:就是在原来的基础上,去掉自定义构造函数的函数体,后面加冒号,写上属性(形参)这种:下面的示例,abc就是我们的属性,a1,b1,c1就是我们的形参:
5.类作为成员变量
打印结果:
这个就是想要说明:A类里面有B成员变量,B也是一个类,这个题就是person类里面有person成员变量,phone也是一个类,执行构造的时候,先执行B的构造,再执行A的构造,执行析沟的时候,先执行A的析构,后执行B的析构,就这个顺序的问题。
这篇关于C++类和对象(HM)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!