Qt并不是一定要用来做界面开发,其实Qt内部的很多非界面模块也十分优秀,本文从紧接着上一篇文章,继续介绍使用QObject做基类来开发模块。
内存管理是C/C++的核心技术,也是一个C/C++工程师实现质的飞跃的门槛。在Qt框架下,内存开辟和释放技术是无处不在。 此处不再详细介绍C++指针的一些基本知识,有兴趣可以阅读相关文章和书籍,在博客后期也会同步公号(不如起而行之)写一些关于C++指针介绍的文章。
内存开辟离不开指针定义符号“*”和取地址符“&”;而在C++中可以开辟的内存有两个主要区域:堆区和栈区。 普通定义的变量如“int i=1”都是定义在栈区,但是栈区对计算机内存来说是极其宝贵的资源,通常只会在小的作用域类使用栈区定义的变量,那么如“int *p = &i”指针p也指向的栈区一段内存,如果您的项目中所有的变量都是通过普通定义到栈区,极可能造成栈区溢出,内存崩溃。 因此,对于占用内存空间长或者生命周期长的变量必须要在堆区去开辟,而在堆区开辟变量空间只能使用指针,这也是为什么指针是C++编程的核心技术。 而在堆区开辟内存空间需要使用关键字 “new”和“delete”。如“int *p = new int(3)”表示在堆区开辟一个int空间,初始值为3,用p指向这段空间。
接着上一篇的项目文档,对头文件做一些修改:
后面需要在堆区开辟一个区域存放字符串需求,此处使用Qt使用的高效序列QVector,先在头文件包含“#include ”,QVector是C++的vector模板类的Qt版本,二者用法基本相似,可能有一些细微区别。 关于C++模板的使用请关注相关文章或者书籍。然后在头文件的private区域新建一个指针文件m_nameVector,代码如下: 注意,Qt中新建指针变量一定要初始化,如果不初始化可能会造成野指针。此处先将指针变量m_nameVector的值置为空指针nullptr。如果您的指针初始值不好定,也请先将其置为空指针nullptr。此时虽然已经新建了一个指针变量m_nameVector,但是其并未指向任何内存空间,因为其值为空。 指针有一个常用习惯“使用时开辟,使用完就释放”,这也是为了减小计算机内存空间压力。 所以也是为什么我们一般在头文件定义指针时将其置为空。
下一步需要去源文件为指针在堆区开辟空间,一般Qt初始变量喜欢在构造函数里面使用变量{初始化值}的模式。如下: “m_nameVector{new QVector {}}”,其中外面那个“{}”表示对m_nameVector指针变量进行初始化,指向堆区新开辟的空间首地址;里面那个“{}”表示对指针指向的空间进行初始化,如果“{}”中没有内容,表示初始化为“0”,不同类型的变量“0”的含义不一样,这块可以参考C++相关文档。
当然这个初始也可以仿真源文件的任何函数之中,如下: 在使用new从堆区开辟内存空间之后,一定要考虑该空间的释放问题,内存释放使用关键字“delete”。当然开辟的内存可以在源文件的任何位置释放。 一般情况下会放在对象的析构函数之中,本项目的m_nameVector的内存释放如下: 注意,好的内存释放习惯一定是如上三步:
判断指针是否已经被释放,一般就是判断指针的值是否非空,如if(m_nameVector);调用delete释放指针指向的内存空间,delete m_nameVector;为了防止产生野指针,将指针变量赋值为空,m_nameVector = nullptr。堆区内存开辟和释放时C++的核心技术,也是难点技术;对于Qt项目,几乎所有的对象都是直接开辟在堆区,因此了解学习和熟练使用堆区内存开辟和释放是开发Qt项目的必须基本功。后期将继续基于QObject介绍一些非界面技术,如信号与槽机制/事件驱动机制等,请持续关注。
欢迎同好沟通交流,批评指正,欢迎关注我的公号:不如起而行之