鉴于项目之前排查一个偶发的问题,最后居然定位在局部静态变量导致,所以记录一下,同时要明白静态变量的作用, 及使用的场景,否则很容易出错!
具体模拟代码如下:
void Function()
{
static int nIndBac = -1;
if(-1 == nIndBac )
{
nIndBac = m_vecTables.size();
}
m_vecTables.at(nIndBac-1); ///获取容器的东西,最好封装一个接口或者做个判断,不要导致越界
}
///上述接口在不同调用下, m_vecTables的个数不一样,导致越界!
类似的问题之前还遇到如下:
void Function()
{
static CString strUrl ; ///估计本身是好意,避免多次调用GetUrl(), 同时在很多优化中使用此方法缓存数据,避免调用
if(strUrl .isEmpty()) ///也是性能优化的一个点
{
strUrl = theApp.GetUrl( URL_TYPE);
}
strUrl += _T("NewData=Stock"); ///此处会不断增加_T("NewData=Stock")
RequestData(strUrl ); // get的请求下(参数有限制),并且是在一个定时器里面调用函数,最终导致请求失败!
}
以上均由于静态变量不当使用,导致程序莫名其名的现象出现, 为此回顾一下知识点,如下:
关于静态成员初始化问题,如下模拟代码:
///B.h文件
class A; //此处为前置声明, 而不是#include"A.h"
class B
{
static A* m_pA; /// 此处仅仅是声明一个A类静态成员,次时编译并未分配内存,因为仅仅是声明,所以编译不需要知道B /// 是什么结构和内存大小, 也无需分配内存,仅需前置声明即可
static int m_nIndex;
}
///B.cpp
A* B:: m_pA= NULL;
int B::m_nIndex= 0;
A.h文件
class A
{
}
void Function()
{
CString strTmp;
strTmp.Format(_T("%d"), m_nIndex); /// 此处如果没有“int B::m_nIndex= 0”, 编辑报错: LNK2001
if(NULL == m_pA) /// 如果未有上面的,也类同报错
{
m_pB = new A;
}
}
///关于前置声明的使用:
1,首先使用#include “”时,如果两个类之间相互耦合,会出现编辑不错;
2,采用前置声明可以避免上述情况,同时前置声明必须为指针和引用, 建议采用指针,个人喜好,
这样的好处,如果对一个成员变量来说, 如果声明指针,则不需要额外的内存, 同时可以将额外的内存申请延长到具体使用 的时刻,避免非指针的成员对象,在初始化时,即分配内存,如果该成员对象类是一个复杂的对象,此时更是明显!
程序优化中,很多将具体的业务,延长到具体使用时在加载,初始化,如下:
1, 树形控件的加载,可以先加载一层节点,后续在使用时,在动态加载,避免以上就加载所有,尤其整棵树层级比较多时,导致程序初次打开比较慢等!
2, 自绘控件时,出现滚动条很正常, 如果每一次全部自绘,数据量稍微大时,就会导致整个界面很卡,优化点出去之前业务优化,重点关注:在滚动时, 只自绘用户可见区域的数据,这样对性能的提升很大!
以上两点,后续会跟上相关重要的代码逻辑!
本想自己整理,结果看一篇很好的文章就直接连接
https://blog.csdn.net/pathuang68/article/details/4193960;
如上连接为::大神:“玄机逸士”的文章, 很多年前看其写的设计模式专栏,很好,可惜目前看不到了!
相关知识点:
c++对象根据定义的位置不同, 具有不同的作用域和不同的内存分配, 这些知识要点详见:
https://www.cnblogs.com/yyxt/p/4912271.html;
静态局部变量的线程安全性,详见下列:
https://blog.csdn.net/leez0301/article/details/27527793