本文是GeekBand课程体系中,侯捷老师讲课内容的部份内容总结。程序员
参考书籍以下:Effitive C++ 数组
C++ Primer 第五版函数
http://blog.csdn.net/lwbeyond/article/details/6202256 中的部分图片this
构造函数:如 : String(const char* cstr = 0);spa
拷贝构造函数 如 :String(const String& str);.net
拷贝赋值函数 如 :String& operator=(const String& str);指针
析构函数:如 :~String();code
其中,拷贝构造函数、拷贝赋值函数、析构函数被称为C++ 的三大函数!blog
下面以String类进行分析:继承
1 class String 2 { 3 public: 4 String(const char* cstr = 0); 5 String(const String& str); 6 String& operator=(const String& str); 7 ~String(); 8 char* get_c_str() const { return m_data; } 9 private: 10 char* m_data; 11 };
若是上面定义看起来还不够直观,那么从调用函数角度再看下:
String s2("world"); // 构造函数 String s3(s2); //拷贝构造函数 s3 = s1; // 拷贝赋值函数,左边的值给右边,因此称为赋值
经过上面的分析,咱们从形式上看到了三种构造函数的区别。固然若是程序员没写这些代码,程序也会自动生成这些代码~固然自动生成的代码,有时会有所缺陷。下面
仔细分析下各个地方所须要注意的知识要点。
一、构造函数中不带指针的状况
这种状况比较简单,只须要赋给参数的初值便可!通常系统自带生成的构造函数均可以实现。
二、构造函数中若是带有指针的状况
以代码String类为参考。那么每次输入的字符串如何保存呢?可能会想到利用数组,那么则会碰到另一个问题,那就是数组要多大才合适?
好比说保存“hello”、"helloworld".......字符串的长度每次都不是固定的,这里能够采用两种方法解决!
1、利用动态数组去完成,2、利用指针去完成。相对来讲,指针更灵活一些。因此这里采用指针,并且STL库里也是采用指针的方法去完成的
那么指针是如何肯定字符串大小的呢?
这里也有两种方法,一种是指针指向头部,利用结束符'\0'进行判断
另外一种第一个字符保存长度大小,后面指针指向实际数据便可。
这里面采用了 http://blog.csdn.net/lwbeyond/article/details/6202256 中的部分图片。
原始数据,一个指针指向了数据
浅拷贝:拷贝的只是指针,这种状况下会出现各类问题!
深拷贝:
若是拷贝构造函数中不含指针的话,那么编译器会自动生成拷贝构造函数,既看,只会一位、一位的进行赋值操做。因此此时采用系统默认的状况便可
但若是拷贝构造函数中含有指针,指针也是4个字节的数据,若是还才有一位一位的进行赋值,这样,拷贝过来的指针就会与原指针指向同一个地方。既浅拷贝。
因此若是类中有指针,咱们采用的本身写的构造函数,这时对应的即是深拷贝!
1 inline 2 String::String(const String& str) 3 { 4 m_data = new char[strlen(str.m_data) + 1]; 5 strcpy(m_data, str.m_data); 6 }
这里采用String (const String &str),说明它只接受 “它本身这样的东西” 因此咱们采用new 先建立一个空间大小能够保持复制过来的数据
而后再赋给数据便可
(PS:new 这里面也是采用malloc 进行开辟空间的)
首先观察下String类的拷贝赋值函数
1 inline 2 String& String::operator=(const String& str) 3 { 4 if (this == &str) 5 return *this; 6 7 delete[] m_data; 8 m_data = new char[strlen(str.m_data) + 1]; 9 strcpy(m_data, str.m_data); 10 return *this; 11 }
经过观察 把S2 = S1,实际上就是完成操做符重载的过程(operator+)以下:
一、先删除S2本身自己的内存;
二、而后从新分配一块与S1大小相同的内存;
三、再把S1的内容拷贝到S2上便可。
~~满满的都是套路~~
那么判断 this 与&str 是什么东西?为何要这么作?
简单的思考就是,节省效率吗,单并非主要缘由,下面采用侯捷老师课程中的资料解释下:清晰明了!
inline String::~String() { delete[] m_data; }
通常来讲,会隐式的自动调用析构函数,因此不少状况下没必要写出来。
然而,若是有指针,仍是要自动进行释放掉,不然会引发内存泄露等问题。
析构函数中还对应着继承、委托等各类状况下的析构顺序等,这些留着下篇进行分享。
————以上这些均来自GeekBand,侯捷老师授课内容。侯捷老师具备丰富的C++知识,听课后收获很大。
By NiceCoder