关于C++默认拷贝构造函数产生的问题的讨论
对于拷贝构造函数,我前面的博文有提起过,不过,有的时候,浅拷贝和深拷贝真的很难理解,所以,我们再进行关于拷贝构造函数的一些讨论。
大家都整到拷贝构造函数分为浅拷贝和深拷贝,系统默认的拷贝构造函数是浅拷贝。
默认拷贝构造函数以内存拷贝的方式将旧有对象的内存空间拷贝到新对象的内存空间。
如果类中有指针类型的类型的时候,默认拷贝构造函数只能复制指针属性的值,而不能复制指针属性所指向的内存,此时,如果我们自己不显式定义拷贝构造函数,那么我们在编程的时候,可能会出现很诡异的问题。
显式定义拷贝构造函数来完成指针属性等需要特殊处理的属性的拷贝工作。
The Number one : 我们先来看浅拷贝带来的问题
---------------------我是分割线------------------------
- # include <iostream>
- using namespace std;
- class Car
- {
- private:
- char* brand;
- float price;
- public:
- Car(const char* sz, float p)
- {
- //构造函数中为brand分配内存
- brand = new char[strlen(sz)+1];
- strcpy(brand, sz);
- }
- ~Car
- {
- //析构函数中释放申请的内存
- delete[] brand;
- cout << " Clear is over ! " << endl;
- }
- void just_print()
- {
- cout << "brand : " << brand << endl;
- cout << "price : " << price << endl;
- }
- };
- int main(void)
- {
- Car car_one("BMW",120);
- car_one.just_print();
- //调用默认的拷贝构造函数
- Car car_two(comp_one);
- car_two.print();
- return 0;
- }
----------------------------------------------------------------------------
这个程序运行失败,代码分析:
1、car_two(car_one)等价于
car_two.brand = car_one.brand;
car_two.price = car_one.price;
2、经过赋值操作后,两个对象中的指针指向的是同一块动态内存,当car_one和car_two撤销时,其释放函数都要释放同一块动态内存内存,可是,两个对象撤销有先有后,一旦一个对象被撤销,另一个对象的brand指针变速"野指针",使用该指针再次释放同一块动态内存会引发内存错误。
不仅仅是重复释放内存的问题,还会出现其他问题:
-------------------------------------------------------------------------------
- int main(void)
- {
- Car car_one("Dell", 7000);
- if(true)
- {
- car car_two(car_one);
- car_two.print();
- }
- //car_one.brand指向的动态内存此时已经被释放
- car_one.print();
- return 0;
- }
-------------------------------------------------------------------------------------------
由于car_two是在if结构中定义的局部对象,因此if结构退出时,car_two被撤销,系统自动调用其析构函数,释放了car_two.brand所指向的动态内存,由于car_one和car_two值相同,此时car_one.brand已无所指,成了野指针,此时,对该指针的读写操作都会引发无法预料的错误。
----------------------------------------------------------------------------
此时,我们就需要自己来定义拷贝构造函数:
----------------------------------------------------------------------------
- //显式定义构造函数
- # include <iostream>
- # include <cstring>
- using namespace std;
- class Car
- {
- private:
- char* brand;
- float price;
- public:
- Car(const char* sz, float p)
- {
- brand = new char[strlen(sz)+1];
- strcpy(brand, sz);
- price = p;
- }
- //自定义拷贝构造函数
- Car(const Car& cp)
- {
- //重新为brand开辟与cp.brand同等大小的内存空间
- brand = new char[strlen(cp.brand) + 1];
- //
- strcpy(brand, cp.brand);
- price = cp.price;
- }
- ~Car()
- {
- delete[] brand;
- cout << "clear over " <<endl;
- }
- void print()
- {
- cout << "brand " << endl;
- cout << "price " << endl;
- }
- };
- int main(void)
- {
- Car car_one("Dell", 8999);
- car_one.print();
- //
- Car car_two(car_one);
- car_two.print();
- //没有采用brand = cp.brand 这种直接直接赋值,而是重新申请动态内存,使用
- //库函数strcpy实现了字符串的复制
- //car_one.brand和car_two.brand指向两块不同的内存,避免了错误
- return 0;
- }
------------------------------------------------------------------------------------------
***提一点,自定义的拷贝构造函数,***也重载operator=运算符!
-----------------------------------------------------------------------------------------
相关文章
- 谷歌发论文披露TPU详细信息,比GPU、CPU快15-30倍
- 万维网之父获2016年图灵奖,专访Tim Berners-Lee: 我创建万维网的初衷
- 统治 VR 界,英特尔绝不只是说说而已
- 苹果自研芯片传言证实,被“抛弃”的Imagination股价跌70%
- Cloudera将于4月底登陆纽交所,基于Hadoop的商业公司前景何在?
- Siri之父揭秘人工智能产品如何成功创造千亿市场
- 重磅 | 谷歌无人驾驶自行车横空出世 我可能看了假的黑科技
- 互联网公司愚人节策划大盘点,在恶搞界谁是老大?
- 他去数了纽约街道上的口香糖渍,竟发现一道贫富鸿沟
- 可口可乐从此彻底废除“首席营销官”,设立“首席增长官”
- 阿里新生的面试经,与老人分享的职业进阶攻略及规划
- 阿里云AI产品全景图首次公开 机器学习平台PAI2.0发布 | 阿里云栖大会
- 马斯克的“半机械人”还没出现,这位日本少年却已经可以让你变身“半机械人”了
- Elon Mask又搞大事情:新公司要将人脑与机器连接,给大脑上传想法不再是科幻
- PL/SQL学习笔记(五)
- 张志华:机器学习的发展历程及启示
- 我2年学习编程的经验总结
- 关于腾讯微博之死,离职员工所了解的真相
- 程序员学习编程需要攻克的8个障碍
- 程序员跳槽的10个建议