当前位置: 首页 > news >正文

垃圾回收算法

文章目录

  • 一、引用计数 (Reference Counting)
  • 二、标记-清除 (Mark-Sweep)
  • 三、标记-整理 (Mark-Compact)
  • 四、分代回收 (Generational)


一、引用计数 (Reference Counting)

原理:每个对象维护引用计数,当计数归零时释放内存。

C++示例:

#include <iostream>

class RefCounted {
    int count = 0;

public:
    void addRef() { count++; }
    void release() {
        if (--count == 0) {
            delete this;
        }
    }

protected:
    virtual ~RefCounted() = default; // 允许派生类析构
};

class MyObject : public RefCounted {
public:
    MyObject() { std::cout << "Created\n"; }
    ~MyObject() { std::cout << "Destroyed\n"; }
};

int main() {
    MyObject* obj = new MyObject();
    obj->addRef(); // 引用计数=1

    obj->addRef(); // 引用计数=2
    obj->release(); // 引用计数=1

    obj->release(); // 引用计数=0,触发析构
    return 0;
}

缺点:无法处理循环引用(如A引用B,B引用A)。

二、标记-清除 (Mark-Sweep)

原理:从根对象出发标记所有可达对象,清除未标记的。

C++示例:

#include <iostream>
#include <vector>

class GCObject {
    static GCObject* head;  // 全局对象链表
    GCObject* next = nullptr;
    bool marked = false;

public:
    GCObject() { // 添加到链表
        next = head;
        head = this;
    }

    virtual ~GCObject() {}

    virtual void markChildren() {} // 标记引用的子对象

    void mark() {
        if (marked) return;
        marked = true;
        markChildren(); // 递归标记子对象
    }

    static void sweep() {
        GCObject** curr = &head;
        while (*curr) {
            GCObject* obj = *curr;
            if (!obj->marked) {
                *curr = obj->next;
                delete obj;
            } else {
                obj->marked = false;
                curr = &obj->next;
            }
        }
    }
};

GCObject* GCObject::head = nullptr;

// 根对象集合
std::vector<GCObject*> roots;

class Node : public GCObject {
public:
    Node* child = nullptr;

    void markChildren() override {
        if (child) child->mark();
    }
};

int main() {
    // 创建对象图:root -> node1 -> node2
    Node* node1 = new Node();
    roots.push_back(node1);

    Node* node2 = new Node();
    node1->child = node2;

    // 执行垃圾回收
    for (auto root : roots) root->mark();
    GCObject::sweep();

    // 手动清除根(示例中未释放roots,实际需管理生命周期)
    return 0;
}

缺点:内存碎片化,需暂停程序运行(Stop-the-World)。

三、标记-整理 (Mark-Compact)

原理:标记后移动存活对象至内存一端,整理后释放剩余空间。

简化示例(通过句柄间接访问对象):

#include <vector>

class Object {
    // 假设所有对象通过Handle访问
};

class Handle {
    Object* ptr;

public:
    Object* get() const { return ptr; }
    void relocate(Object* new_ptr) { ptr = new_ptr; }
};

std::vector<Handle*> handles; // 所有句柄需注册

void compact(std::vector<Object*>& alive) {
    // 移动存活对象到新内存区域
    for (auto& handle : handles) {
        if (/* 对象存活 */) {
            Object* new_addr = /* 新地址 */;
            handle->relocate(new_addr);
        }
    }
    // 释放旧内存
}

缺点:对象移动需更新所有引用,实现复杂。

四、分代回收 (Generational)

原理:按对象存活时间分代(年轻代、老年代),优先回收年轻代。

简化示例

class Generation {
    std::vector<GCObject*> young;
    std::vector<GCObject*> old;

    void promote(GCObject* obj) {
        // 将对象从年轻代晋升到老年代
        old.push_back(obj);
    }

public:
    void collectYoung() {
        // 标记-清除年轻代
        for (auto obj : young) if (isRoot(obj)) obj->mark();
        sweep();
        // 晋升存活对象
        for (auto obj : young) if (obj->marked) promote(obj);
        young.clear();
    }
};

优点:减少扫描范围,提升效率。

相关文章:

  • Freertos中空闲钩子函数的使用
  • 坐标变换及视图变换和透视变换(相机透视模型)
  • 机器学习-05-回归算法-python动画展示
  • 远程登录到Linux服务器
  • QVariantList使用详解
  • Spark(3)vi的基本使用
  • cpp中的继承
  • BUU40 [CSCCTF 2019 Qual]FlaskLight1【SSTI】
  • Kronecker分解(K-FAC):让自然梯度在深度学习中飞起来
  • java基础相关-深拷贝与浅拷贝介绍
  • Android Audio实战——音频相关基础概念(附)
  • LangChain教程 - RAG - PDF摘要
  • Ascend NPU 架构 CANN 平台入门学习
  • 如何用HBase轻松管理海量数据?
  • 深入解析:使用Python爬虫获取京东商品详情原数据API接口
  • 一篇文章介绍前端mitt
  • 操作系统之内存管理
  • 基于GWO灰狼优化的BiLSTM双向长短期记忆网络序列预测算法matlab仿真,对比BiLSTM和LSTM
  • chat2db邀请码
  • Python在实际工作中的运用-CSV数据的几个处理方法
  • 做网站需要向客户了解什么/北京网站快速优化排名
  • 郑州网站建设维护公司/关键词优化系统
  • 模板网站建设价位/百度小说排行榜总榜
  • 哈尔滨市建设安全监察网站/查询网址域名ip地址
  • 礼服外贸网站/网文推广怎么做
  • 营销型网站与普通网站的区别/seo优化案例