深入了解C++(1)——C++内存分配机制

 常常被人问到,会不会写C++,曾经以为了解对面对象编程,了解qt等开源的库之后,就可以称之为会写C++了。但是深入了解之后就会发现,C++其实并不是这么简单。作为本专题的第一篇记录,将从内存分配机制开始深入的剖析C++。

一 C++ 内存分配方式

 在C++中内存被分为五个区分别是:堆、栈、自由存储区、全局/静态存储区、常量存储区。

  • 栈:是分配给函数局部变量的存储单元,函数结束后,该变量的存储单元自动释放,效率高,分配的空间有限。
  • 堆:由new创建,由delete释放的动态内存单元。如果用户不释放该内存,程序结束时,系统会自动回收。
  • 自由存储区:由malloc创建,由free释放的动态内存单元,与堆类似。
  • 全局(静态)存储去:全局变量和静态变量占一块内存空间。
  • 常量存储区:存储常量,内容不允许更改。

    引用自ladybai

 一般而言对于程序员,我们只需要去关注堆和栈的概念。相比堆,栈大量减少了内存的碎片问题,并且计算机在系统底层提供专门的指令执行,而new的机制相比更为复杂所以分配效率相较于栈更慢。

二 内存分配失败

 根据许多血一般的教训,下列的代码在动态分配内存的时候至关重要。

1
2
3
4
5
object* c = new object();
//在较新的标准中,使用 new(nothrow) 才会出现分配失败时返回nullptr
if(c==nullptr){
//错误处理机制
}

 但是其实在较新的C++标准中,出现内存分配失败时会抛出

1
std::bad_alloc

 但是针对这个我们主要需要意识到一个问题,内存的分配可能失败。

三 new/operator new/placement new

 为了防止反复的释放内存,C++除了最基本的new操作之外还提供了placement new的操作。下面简单介绍这三种不同的new操作

  • 运算符 new = 先调用函数 operator new 分配空间 + 然后调用构造函数。
  • 对于operator new 函数内部,他是通过再调用malloc函数,进行空间分配的(当然也可以重写一个自己的空间分配器)。
  • placement new 指的是,不进行分配空间,而是在指定的空间上面进行调用构造函数。当然,在析构的时候,也只能显示的调用析构函数。(因为并不是真正的释放空间)

    引用自爱秋刀鱼的猫

 下面简单给出new的代码。

1
2
3
object* a = new object(); 
char* chunk = new(nothrow) char[10];
object* b = new (chunk) object();

 那么其实来说就是上面的两种new,然后operator new的含义应该是仅分配内存但是不初始化函数。

 针对大多数场景,我们使用普通的new可以完成绝大多数任务。但是极少数情况,我们可能需要反复利用一块极大的内存空间,此时利用placement new可以减少内存空间的申请释放所消耗的时间。

四 总结

 本篇主要简要介绍了C++内存分配的机制,并且了解了针对大块内存反复申请释放采用placement new的操作。本模块将持续更新,介绍更多关于C++更为深入的内容。

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×