C++11读书笔记—7(内存管理)

来源:互联网 发布:cc2541中文数据手册 编辑:程序博客网 时间:2024/04/30 18:30

当你羡慕Java垃圾回收时,你想没想过java的垃圾回收机制靠C++实现的,而其实早先C++版本的实现。

其实C++的内存分配的难点不是把不该回收的回收了。而是有些不像指针的指针很容易识别不了。

一.垃圾回收方式简介

1.引用计数法(Reference Counting Collector)

  引用计数法是唯一没有使用根集的垃圾回收的法,该算法使用引用计数器来区分存活对象和不再使用的对象。一般来说,堆中的每个对象对应一个引用计数器。当每一次创建一个对象并赋给一个变量时,引用计数器置为1。当对象被赋给任意变量时,引用计数器每次加1当对象出了作用域后(该对象丢弃不再使用),引用计数器减1,一旦引用计数器为0,对象就满足了垃圾收集的条件。
  基于引用计数器的垃圾收集器运行较快,不会长时间中断程序执行,适宜地必须 实时运行的程序。但问题也出现了,存在环形引用这一问题。开销也不少,实际上有一定限制。

这就类似于shared_ptr的原理。

2.基于跟踪处理的垃圾回收

(1)标记-清除

标记阶段:当前活动对象为根,从根开始查找引用的可达的堆空间,并做标记。

清除阶段:没被标记的被清除。

特点:肯定会产生大量碎片。(这就产生了标记整理。)

(2)标记-整理

标记阶段:同上

整理阶段:将活的对象向前靠齐。

特点:这就解决了大量碎片,系统开销略大

(3)标记-copy

首先将内存分为from区与to区。开始系统从from分配,from满时from回收。将活的copy到to空间(to区紧凑了)。from全是垃圾了。from,to角色交换下。 

特点:堆利用率只有一半,

二.C++11与垃圾回收

C++由于指针问题,垃圾回收很复杂,你根本不知道有没有 一块被当前指向的空间,经过指针操作会不会就被指向了。C++11因此有最小垃圾回收支持

1.最小垃圾回收支持

C++11对安全的指针进行了定义。C++11术语叫安全派生。安全派生的指针是指向有new分配的对象或其子对象的指针。。安全派生的指针操作包括:

1.解引用基础上的引用,&*p

2.定义明确的指针操作,如p+1

3.定义名确的指针转换,如static_cast<void*>(p)

4.指针和整形之间的reinterpret_cast<intptr_r>(p)

如下面的程序:

int *p = new int(10);int *q = (int*)(reinterpret_cast<long long>(p) ^ 2016);q = (int*)(reinterpret_cast<long long>(q) ^ 2016);

如果使用内存回收机制,那么再使用*q时会出现问题,因为不是安全操作。但是今天,2016.8.4,尚没有一个C++11编译器支持。我估计这个很难,因为这会使之前的很多代码产生颠覆性后果。

如果通知垃圾回收其不得回收内存。可以用declare_reachable();函数

int *p = new int(10);declare_reachable(p);int *q = (int*)(reinterpret_cast<long long>(p) ^ 2016);q = (int*)(reinterpret_cast<long long>(q) ^ 2016);

2.C++11垃圾回收提示

C++11的垃圾回收仅限于new的内存,虽然现在没实现但是为了兼容,还是尽量要这么做。

说明:垃圾回收与delete不冲突




0 0