美文网首页
C++性能优化之一:合理使用内存

C++性能优化之一:合理使用内存

作者: 思考着自己的未来 | 来源:发表于2019-10-04 12:27 被阅读0次

要想在编码过程中,写出高效的代码,是需要自己长期的总结和不断学习的。工作以来,我自己也总结了一些小技巧,可以让你的程序运行的更快、内存空间使用更合理,同时我还会不断地补充该blog,争取建立出一个属于自己的c++ effective系列。

不多说,直接进入正题,以下都是我再编程过程中,总结出来c++高效编码规则,每个topic对应一个规则。

局部变量合理使用

让我们先看一段代码:

for (int i = 0; i < 1000; ++i)
{
    string str = "do some thing:" + int2str(i);
    func(str);
}

这段代码,在循环中使用局部变量拼装函数func的入参,在每次循环过程中,str对象都会执行一次构造函数和析构函数,那么,在这个for循环中,单单是str的组装就耗费了1000次的内存申请和释放,局部变量占用内存小的话,影响不会很大,如果动辄几十、几百kb,那就会造成系统内存使用的波动,那么是不是有更高效的方法?

其实只需要把str变量放到for循环外部声明即可,如下面代码:

string str;
for (int i = 0; i < 1000; ++i)
{
    str = "do some thing:" + int2str(i);
    func(str);
}

这段代码会大大降低内存的申请和释放次数,因为首次循环后,str会申请15个字节的内存空间来容纳现有数据,第二次循环时,在赋值运算符函数中,由于str当前空间已经足够容纳第二次循环的数据,因此我们可以考虑对原有str内存进行复用,所以只存在一次数据拷贝,不存在新的内存申请和释放;到第十次循环时,需要16个字节才能容纳现有数据,因此需要释放str原有内存,申请新的内存。以此类推,我们可以算出1000次循环过程中,只有三次内存申请和释放,大大降低了内存的申请和释放次数。

小结:在循环体中,局部变量如果占用内存空间较大,会造成内存使用不合理,可以考虑放到循环体外声明。

左值引用的合理使用

左值引用提升程序性能的应用场景。
首先是函数入参,看下面两个函数的声明,func1会存在一次str副本的拷贝构造的过程,且退出函数体,还需要释放str,而func2直接将str的地址传入函数体内部,不存在拷贝构造,如果str内存很大,那么节约一次拷贝的收益还是很可观的。

void func1(const string str);  //存在冗余拷贝构造和析构
void func2(const string& str); //直接传递str变量的地址

其次是循环体中,获取数组元素时,如果我们不需要修改原始值,那么应该是使用常引用直接指向数组元素的地址,避免局部变量的冗余的拷贝构造和析构

for (int i = 0; i < arrstrs.size(); ++i)
{
    string str = arrstrs[i];        //存在冗余拷贝构造和析构
    const string& str = arrstrs[i]; //直接使用arrstrs[i]变量的地址
    ...
}

动态数组容量提前设定

分层架构的代码中,经常出现需要对不同层次数据规格进行转换,即把其他层次的数据转化为所在层的数据格式,以下是项目中经常看见的一段代码,主要目的是把第二层的数据转化到第一层坐标数据中,代码如下:

//变量格式声明
typedef struct _FirstLayer_PosData_t
{
    double x;
    double y;
}FirstLayer_PosData_t;
typedef struct _SecondLayer_PosData_t
{
    double x;
    double y;
    int    tag;
}SecondLayer_PosData_t;
vector<FirstLayer_PosData_t> arrfir;
vector<SecondLayer_PosData_t> arrsec;
//层数据转化代码
for (int i = 0; i < arrsec.size(); ++i)
{
    FirstLayer_PosData_t stFirstLayerPos;
    stFirstLayerPos.x = arrsec[i].x;
    stFirstLayerPos.y = arrsec[i].y;
    arrfir.push_back(stFirstLayerPos);
}

这段代码可以这样改进,其实我们要拷贝的元素个数是已知的,因此我们可以直接将arrfirst数组大小设置为arrsecond的大小即可,这就避免了在循环体中动态的去扩容(每次扩容的成本是先申请新的内存空间,将旧内存空间数据拷贝到新内存空间,然后释放旧内存空间),改进代码如下:

arrfir.setsize(arrsec.size());
for (int i = 0; i < arrfir.size(); ++i)
{
    FirstLayer_PosData_t stFirstLayerPos;
    stFirstLayerPos.x = arrsec[i].x;
    stFirstLayerPos.y = arrsec[i].y;
    arrfir[i] = stFirstLayerPos;
}

仔细观察下,其实还有优化空间,局部变量是可以避免的,直接使用引用代替第一层数组的每个元素即可,最终优化代码如下:

arrfir.setsize(arrsecond.size());
for (int i = 0; i < arrfirst.size(); ++i)
{
    FirstLayer_PosData_t& stFirstLayerPos = arrfir[i];
    stFirstLayerPos.x = arrsec[i].x;
    stFirstLayerPos.y = arrsec[i].y;
}

move语义的合理使用

TODO

相关文章

  • C++性能优化之一:合理使用内存

    要想在编码过程中,写出高效的代码,是需要自己长期的总结和不断学习的。工作以来,我自己也总结了一些小技巧,可以让你的...

  • Android性能优化

    原文地址 点击进入 Android性能优化 合理管理内存 节制的使用Service 如果应用程序需要使用Servi...

  • Android性能优化

    Android性能优化 合理管理内存 节制的使用Service 如果应用程序需要使用Service来执行后台任务的...

  • Part1_Android性能优化

    Android性能优化 合理管理内存 节制的使用Service 如果应用程序需要使用Service来执行后台任务的...

  • 补全计划| Android性能优化分析

    Android性能优化 合理管理内存 节制的使用Service 如果应用程序需要使用Service来执行后台任务的...

  • 内存池

    参考资料 C++内存池介绍与经典内存池的实现 C++ 应用程序性能优化,第 6 章:内存池 linux c++ 内...

  • Flutter相关优化

    性能优化 1、内存优化使用flutter performance等工具查看内存和帧率使用DevTools来gc查看...

  • iOS 性能优化内存优化学习

    iOS APP渲染性能优化iOS性能优化之内存(memory)优化iOS内存和性能优化

  • 简述http缓存

    简介 网站性能第一优化定律:优先考虑使用缓存优化性能。合理的使用缓存,对网站的性能优化的意义重大。以下对于缓存,都...

  • Android性能优化篇之内存优化--内存泄漏

    引言 1. Android性能优化篇之内存优化--内存泄漏 2.Android性能优化篇之内存优化--内存优化分析...

网友评论

      本文标题:C++性能优化之一:合理使用内存

      本文链接:https://www.haomeiwen.com/subject/sjdoyctx.html