–本文章来自侯捷老师的课程和自己的理解形成的笔记
若有错误,欢迎指正
接下来介绍带指针的类:
带指针的类之所以需要单独注意,是因为这些类一般都会要自己重新写拷贝构造,拷贝赋值,以及析构函数。
因为编辑器默认的函数只会拷贝指针。
首先,构造函数和析构函数需要使用new和delete对空间进行操作:
需要注意的是,new【】需要搭配delete【】。因为这样编译器才会知道要多次调用析构函数来归还空间。所以一定要加【】。
之所以需要自己的拷贝函数,是因为编译器在拷贝的时候,使用默认的拷贝函数,只会拷贝指针,而没有创建一片新的内存。 拷贝前后两个对象所指向的内存区域是同一个区域。这是十分危险的。
这种拷贝方式叫做浅拷贝,浅拷贝会造成如上图这样的内存泄漏。只有自己开辟了内存的拷贝才叫做深拷贝,才是安全的。
因此,拷贝构造函数应当自己开辟空间:
而拷贝赋值函数则稍微复杂一点:
(1)首先需要清理原本的内存空间。
(2)分配与需要拷贝的内容相同大小的空间。
(3)复制
同时,检测是否自我赋值也是必要的。因为这要考虑到将来可能出现的自我赋值的正确性。
如果没有自我赋值检测的话,那么第一步就会销毁自身空间,造成错误。
接下来介绍栈和堆:
stack(栈):**是存在于作用域内的一块内存空间。**在函数本体内声明的任何变量,其所使用的内存块则来自于stack。
Heap(堆):**是指由操作系统提供的一块,全局内存空间。**程序可以动态分配从中获得若干块(使用new和delete操作)
但是用static关键字声明的栈对象,则不会随着作用域的消失而消亡,会一直存在到程序结束为止。
new在编译器中的工作过程如下:
先分配内存,再调用构造函数
delete的工作方式如下:
先调用析构函数,再释放内存。
进一步补充static:
在数据/成员函数之前加static可以使其变为静态。
静态数据在内存中只有一份,不会因为实例化对象而变多。
静态函数没有this指针,只能用来处理静态数据。
同时,静态数据在类外还需要声明,相当于初始化。