C++单例模式 (Singleton Pattern)

单例模式 (Singleton Pattern) 是软件设计模式中最基础、也是自动驾驶系统中最常用的一种模式。

为了让你彻底理解,我们还是用生活例子,结合代码来拆解。


一、 核心概念:

单例模式的定义 :确保一个类只有一个实例 (Instance) ,并提供一个全局访问点来获取它。

生活中的例子:
  • 公司公章:只有一枚。谁要盖章,都得去找那一枚章。
代码中的含义:

在你的代码里,PlanContext 就是那个"公章"。

  • 错误的做法 :每次要用数据,就 new PlanContext()

    • 后果:感知模块往"公章A"里写了障碍物,规划模块去"公章B"里读数据。结果读了个寂寞,车子撞墙。
  • 单例的做法 :全程序禁止 new,只能通过一个特定的函数(比如 Instance())拿到那唯一的一个对象。


二、 C++ 代码怎么写?

这是 C++11 之后最标准、最简洁、线程安全 的写法(被称为 Meyers' Singleton)。请把这段代码刻在脑子里:

cpp 复制代码
class PlanContext {
private:
    // 1. 构造函数私有化 (Private Constructor)
    // 意思:禁止外部随便 new!只有我自己能生我自己。
    PlanContext() { 
        std::cout << "PlanContext 初始化了(只会出现一次)" << std::endl;
    }

public:
    // 2. 删除拷贝构造和赋值操作 (Delete Copy)
    // 意思:禁止克隆!禁止影分身!保证独一无二。
    PlanContext(const PlanContext&) = delete;
    void operator=(const PlanContext&) = delete;

    // 3. 全局访问点 (Global Access Point)
    // 意思:想要用我?调这个函数。
    static PlanContext& Instance() {
        // 关键点:static 局部变量
        // 特性:C++11 保证了它是线程安全的,且只会初始化一次
        static PlanContext instance; 
        return instance;
    }

    // --- 具体的业务数据 ---
    void updateData() { ... }
};

// 使用方法:
int main() {
    // PlanContext p = new PlanContext(); // 报错!不让你 new
    
    // 正确用法:直接找 Instance 要
    PlanContext::Instance().updateData(); 
}

三、 为什么 PlanContext 必须是单例?

结合你的架构图,原因有两个:

1. 数据一致性 (Data Consistency)

你的系统是一个流水线: 感知 -> 写入 -> PlanContext -> 读取 -> 规划 如果 PlanContext 不是单例,感知写到了对象 A,规划读的是对象 B,那规划模块永远拿不到最新的路况。只有大家共用一个对象,才能保证**"你写的就是我读的"**。

2. 节省资源 (Resource Management)

虽然 PlanContext 可能不大,但如果是一些像 MapEngine(地图引擎)这样的类,加载一次地图要吃掉 2GB 内存。如果你不小心 new 了 10 次,20GB 内存没了,电脑直接死机。单例保证了它只占一份内存。


四、 单例模式的"坑"

虽然它好用,但也不要滥用。

  1. 它本质上是全局变量 : 因为谁都能访问它,谁都能改它。如果代码里哪个角落偷偷改了数据,很难查出来是谁干的。(所以我们要加 Mutex 锁来保护)。

  2. 生命周期难以控制: 它通常在程序启动时出生,程序结束时销毁。如果你想中途把它销毁释放内存,比较麻烦。

五、 总结

当你看到代码里写着 ::Instance() 或者 ::getInstance() 时,脑子里要立刻反应过来:

  1. 这是一个单例。

  2. 全公司只有这一份。

  3. 大家都在抢着用它,所以里面肯定有锁 (Mutex)。

相关推荐
草履虫建模14 小时前
力扣算法 1768. 交替合并字符串
java·开发语言·算法·leetcode·职场和发展·idea·基础
naruto_lnq16 小时前
分布式系统安全通信
开发语言·c++·算法
天才奇男子16 小时前
HAProxy高级功能全解析
linux·运维·服务器·微服务·云原生
Jasmine_llq16 小时前
《P3157 [CQOI2011] 动态逆序对》
算法·cdq 分治·动态问题静态化+双向偏序统计·树状数组(高效统计元素大小关系·排序算法(预处理偏序和时间戳)·前缀和(合并单个贡献为总逆序对·动态问题静态化
小李独爱秋16 小时前
“bootmgr is compressed”错误:根源、笔记本与台式机差异化解决方案深度指南
运维·stm32·单片机·嵌入式硬件·文件系统·电脑故障
qq_2975746716 小时前
【实战教程】SpringBoot 实现多文件批量下载并打包为 ZIP 压缩包
java·spring boot·后端
老毛肚16 小时前
MyBatis插件原理及Spring集成
java·spring·mybatis
学嵌入式的小杨同学16 小时前
【Linux 封神之路】信号编程全解析:从信号基础到 MP3 播放器实战(含核心 API 与避坑指南)
java·linux·c语言·开发语言·vscode·vim·ux
lang2015092816 小时前
JSR-340 :高性能Web开发新标准
java·前端·servlet
Re.不晚16 小时前
Java入门17——异常
java·开发语言