【C++深度剖析教程14】经典问题解析三之关于赋值的疑问
2018-01-22 00:53
387 查看
今天我们来总结一下,之前所学C++中所遇到的一些经典的问题。
第一个疑问是:
-什么时候需要重载赋值操作符
-编译器是否提供默认的赋值操作?
解答:
*编译器为每个类默认重载了赋值操作符
*默认的赋值操作符仅完成了浅拷贝
*当需要进行深拷贝时,就需要进行赋值操作符的重载
*赋值操作符与拷贝构造函数有相同的存在意义。
下面我们还是给出一个例子程序来分析:
上面这个程序运行结果为:
上面的程序很简单,我就不多分析了,如果我想将以上的程序注释掉的那一行t2 = t1取消注释加上呢?运行结果如下:
可以看出,运行结果崩溃,出现了内存错误。
是什么原因呢?
由于我们让t2的堆空间指向了t1,那么再释放堆空间的时候,就需要释放两次,可是我只有一个堆空间,释放两次肯定要出现内存错误的。
下面我们给出解决办法(进行深拷贝):
运行结果为:
以上程序的分析,已经在程序的注释里面了,已经说得很清楚。
总结:
一般性原则:
在需要进行深拷贝的时候,必须进行赋值操作符的重载。
赋值操作符与拷贝构造函数有同等重要的意义。
任何文字的说明都无法比真正的代码能让你更加明白其中的原理!!!多动手写~
想一起探讨以及获得各种学习资源加我(有我博客中写的代码的原稿):
qq:1126137994
微信:liu1126137994
可以共同交流关于嵌入式,操作系统,C++语言,C语言,数据结构等技术问题。
第一个疑问是:
-什么时候需要重载赋值操作符
-编译器是否提供默认的赋值操作?
解答:
*编译器为每个类默认重载了赋值操作符
*默认的赋值操作符仅完成了浅拷贝
*当需要进行深拷贝时,就需要进行赋值操作符的重载
*赋值操作符与拷贝构造函数有相同的存在意义。
下面我们还是给出一个例子程序来分析:
#include <iostream> #include <string> using namespace std; class Test { int* m_pointer; public: Test() { m_pointer = NULL; } Test(int i) { m_pointer = new int[i]; } void print() { cout << "m_pointer = " << m_pointer << endl; } ~Test() { delete m_pointer; } }; int main() { Test t1 = 1; Test t2; //t2 = t1; t1.print(); t2.print(); return 0; }
上面这个程序运行结果为:
上面的程序很简单,我就不多分析了,如果我想将以上的程序注释掉的那一行t2 = t1取消注释加上呢?运行结果如下:
可以看出,运行结果崩溃,出现了内存错误。
是什么原因呢?
由于我们让t2的堆空间指向了t1,那么再释放堆空间的时候,就需要释放两次,可是我只有一个堆空间,释放两次肯定要出现内存错误的。
下面我们给出解决办法(进行深拷贝):
#include <iostream> #include <string> using namespace std; class Test { int* m_pointer; public: Test() { m_pointer = NULL; } Test(int i) { m_pointer = new int(i); } Test(const Test& obj) //深拷贝函数的构造 { m_pointer = new int(*obj.m_pointer);//先申请一个int型的堆空间,然后给堆空间里加值 //这个值是obj这个对象所指的m_pointer指针所指的值 //,然后让m_pointer再指向这个值的堆空间 } Test& operator = (const Test& obj) //重载赋值操作符,返回类型必须是引用类型, //参数必须是const类型的 { if( this != &obj ) //防止自赋值,当前对象的地址与传进来的参数的地址不一样 { delete m_pointer; m_pointer = new int(*obj.m_pointer); } return *this; //返回当前对象的值 } void print() { cout << "m_pointer = " << hex << m_pointer << endl; } ~Test() { delete m_pointer; } }; int main() { Test t1 = 1; //Test类对象t1内部的指针m_pointer执指向的堆空间的值为1 Test t2; //Test类对象t1内部的指针m_pointer执指向的堆空间为空 t2 = t1; //因为要实现给t2一个单独的堆空间,也就是实现深拷贝,所以需要上面的赋值操作符的重载以及构造一个拷贝构造函数 t1.print(); //打印的是堆空间的地址值,16进制 t2.print(); return 0; }
运行结果为:
以上程序的分析,已经在程序的注释里面了,已经说得很清楚。
总结:
一般性原则:
在需要进行深拷贝的时候,必须进行赋值操作符的重载。
赋值操作符与拷贝构造函数有同等重要的意义。
任何文字的说明都无法比真正的代码能让你更加明白其中的原理!!!多动手写~
想一起探讨以及获得各种学习资源加我(有我博客中写的代码的原稿):
qq:1126137994
微信:liu1126137994
可以共同交流关于嵌入式,操作系统,C++语言,C语言,数据结构等技术问题。
相关文章推荐
- 【C++深度剖析教程15】经典问题解析之关于string的疑问
- 《 C++深度剖析》学习日志十九——经典问题解析二
- [笔试题 2][c/c++]关于指针直接赋值问题
- 关于vs2010 C++编译链接总是出现“LNK:2019 无法解析的外部符号”的问题
- 关于编码问题的深度解析
- c++学习笔记(13.专题三经典问题解析)
- [笔试题 2][c/c++]关于指针直接赋值问题
- java经典面试题深度解析免费视频教程分享
- 关于C++的疑问剖析
- C++中 关于结构体中有char *类型的指针 赋值问题
- C++中的经典问题解析
- 百度云盘分享视频教程:java经典面试题深度解析
- java经典面试题深度解析免费视频教程分享
- 免费视频教程:java经典面试题深度解析
- 一道经典的C++题,关于分钱的问题,适合新手阅读(黑客X档案论坛题目) [c#]
- c++学习笔记(5.专题一经典问题解析)
- 免费视频教程分享 :java经典面试题深度解析
- C++关于函数声明和定义中参数赋值为0调用问题演示
- 免费视频教程:java经典面试题深度解析
- 关于c++名字解析的一个问题:名字空间污染