更多课程 选择中心

C/C++培训
美国上市教育机构

400-111-8989

C++培训

C++基础-内存管理

  • 发布:C++培训
  • 来源:代码备忘录
  • 时间:2019-11-29 14:06

本文主要是堆、栈和RAII,属于内存管理的范畴吧。说一下自己的心得体会。

堆和栈的概念

在早期学生时期写代码几乎是没有内存管理的概念的,什么时候该用new/malloc(堆),什么时候用局部变量(栈),完全是看心情的。后来工作中开始对大对象使用new/malloc,小对象使用局部变量,多少算大?多少算小?差不多十年前有个商业软件叫PCLINT,可以统计单个函数栈的内存使用(统计局部变量),那时我所在部门,没记错的话超过2K会告警。到了Modern C++,我所得到的大部分规则是:尽量避免动态内存分配。当然我觉得这大部分基于一点:就是现代的软硬件系统,内存大小越来越不是约束条件了。只要不是超级大对象,在栈上分配往往意味着更好的性能。举个列子:

void func() { // 这是一个不好的例子 // 当然还能有更糟糕的写法, 比如直接new auto foo = std::make_unique<Object>(); foo->balabala(); // 好的实践 Object bar; bar.balabala();}

首先,在Modern C++里面我们已经不提倡直接使用new/delete了,我觉得除非是在编写一些内存管理相关的公共库或模板类,否则都应该遵循这一准则。取而代之的是使用智能指针,比如 unique_ptr。

然后针对上面这段代码,如Object不是一个大对象,那么就没有必要去堆上申请空间来维护他,因为使用栈上的局部变量更加高效(在我看来C++的很多设计始终维持不变的原则就是保持高效)。

RAII

RAII (Resource Acquisition Is Initialization) 可以参考C++ Core Guidelines 里面的介绍:R.1: Manage resources automatically using resource handles and RAII (Resource Acquisition Is Initialization): isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines.html#Rr-raii 作为 Core Guidelines资源管理的第一条规则,自然是有道理的。

RAII 的主要目的是为了避免或者减少手动地管理资源,从而避免各种资源泄漏。

对于RAII其实之前我一直是有顾虑的,原因主要是考虑当处理一些Legacy的C接口的时候,如果把一些资源初始化的接口构造函数里面调用,那么返回失败了应该在构造函数里面抛异常么?如果抛了异常,那么析构函数是不会被调用的。基于以上原因在编写Legacy资源的Wrapper类的时候是需要小心处理的,不然反倒容易被自己迷惑。

关于内存管理的一些补充

在Modern C++的内存使用中,还有一些之前的心得,列出来供参考。

如何避免使用裸指

当然是尽量使用引用,或者使用智能指针了。当然有时候你需要代码足够地高效从而使用引用,但是这个引用又可能为空,那么问题就来了,因为C++目前没有NullReference这个东西,那么只好考虑一下裸指针了。

关于智能指针的使用

    尽量使用make_unique, make_shared 来初始化智能指针,因为相对来说他们是Exception Safe的,并且有着更好的效率。

    不要再使用auto_ptr了,已经过时了,更加不要再实际项目中自己编写Memory Guard了,当然作为理解概念练手还是有必要的。

    shared_ptr的使用要谨慎,考虑一下真的需要share么?是不是引用就可以了?循环引用则需要引入weak_ptr。

本文内容转载自网络,本着分享与传播的原则,版权归原作者所有,如有侵权请联系我们进行删除。

预约申请免费试听课

填写下面表单即可预约申请免费试听!怕钱不够?可就业挣钱后再付学费! 怕学不会?助教全程陪读,随时解惑!担心就业?一地学习,可全国推荐就业!

上一篇:C++数组相关
下一篇:C++ Swap函数有几种写法?

C++基础-内存管理

C++数组相关

C++冒泡排序是这么回事

C++的#include_next指令

选择城市和中心
黑龙江省

吉林省

河北省

湖南省

贵州省

云南省

广西省

海南省