2026/5/21 13:42:05
网站建设
项目流程
亿联时代网站建设,怎么判断网站是否被k,wordpress 外贸 插件,石狮住房和城乡建设局网站《你真的了解C吗》No.016#xff1a;智能指针的幻觉——unique_ptr 与 shared_ptr 的设计哲学
导言#xff1a;为什么 new 是危险的#xff1f;
在传统的 C 教程中#xff0c;我们学习了用 new 分配内存#xff0c;用 delete 释放内存。然而#xff0c;在逻辑复杂的工程中…《你真的了解C吗》No.016智能指针的幻觉——unique_ptr 与 shared_ptr 的设计哲学导言为什么new是危险的在传统的 C 教程中我们学习了用new分配内存用delete释放内存。然而在逻辑复杂的工程中由于异常跳转、提前返回或逻辑疏忽delete往往会被漏掉导致内存泄漏或者被多次执行导致双重释放。智能指针Smart Pointers的本质并不是指针它们是封装了原始指针的“管家”对象。它们利用了 C 的 RAII 机制当管家对象在栈上被销毁时它会自动在析构函数里帮我们清理堆上的内存。一、unique_ptr极致的独占与零开销unique_ptr遵循的是“独占所有权”模型。它是最符合 C “零开销抽象”原则的工具。设计哲学一个资源在同一时刻只能有一个主人。禁止拷贝你不能把一个unique_ptr赋值给另一个因为这会导致两个主人争夺同一个资源。所有权转移你必须使用std::move()显式地将所有权“转让”出去。性能在编译器优化后unique_ptr的性能与原始指针完全一致。它不占用额外的内存也没有运行时的计时开销。二、shared_ptr复杂的共享与代价当你确实需要多个对象共同拥有同一块内存时例如图论中的节点shared_ptr就上场了。它通过**引用计数Reference Counting**来工作。1. 内存结构的细节为什么是两个指针一个shared_ptr在栈上占用的空间通常是2 个指针的大小在 64 位系统上为 16 字节它内部包含原始指针Stored Pointer直接指向堆上的对象。控制块指针Control Block Pointer指向一个独立的、位于堆上的“控制块”。2. 控制块里藏着什么控制块Control Block是shared_ptr共享机制的核心它由所有指向同一个对象的shared_ptr共同维护内部包含强引用计数Strong Ref Count记录当前有多少个shared_ptr指向该对象。当这个计数归零对象被销毁。弱引用计数Weak Ref Count记录当前有多少个weak_ptr指向该对象。自定义删除器/分配器如果你指定了如何销毁对象。3. 代价分析内存开销每个shared_ptr实例在栈上比普通指针大一倍。此外控制块在堆上需要额外申请空间通常约 16-32 字节。性能损耗引用计数的修改必须是原子的Atomic。这意味着即使在单线程逻辑中每当你拷贝或销毁一个shared_ptrCPU 都要执行昂贵的原子操作来保证多线程环境下的数据一致性。三、weak_ptr打破“死亡环抱”shared_ptr有一个致命的弱点循环引用。如果 A 指向 BB 也指向 A它们的计数永远不会归零内存将永久泄漏。weak_ptr是为了观察shared_ptr而存在的“旁观者”它不会增加引用计数。它不拥有资源。它能感知资源是否已经被销毁通过lock()转换为shared_ptr来安全访问。四、 避坑指南为什么make_shared更受欢迎永远优先使用std::make_unique和std::make_shared而不是直接new出来丢给指针安全性防止在构造函数参数传递过程中发生异常导致内存泄漏。效率针对 shared_ptr传统的shared_ptrT(new T())需要两次堆内存申请一次给对象一次给控制块。而std::make_shared会一次性申请一块足够大且连续的内存同时容纳对象和控制块。这减少了内存碎片且对 CPU 缓存极其友好。五、 总结不要为了“安全”而滥用很多初学者因为害怕内存泄漏将项目中所有的指针都改成了shared_ptr。这是一种危险的倾向**默认使用unique_ptr**它清晰地表达了所有权且性能最高。**只有在必须共享时才使用shared_ptr**。原始指针仍有用途如果只是为了“观察”一下对象而不涉及所有权即你保证对象的生命周期比这个指针长使用原始指针Raw Pointer往往比weak_ptr更高效、更直接。下一篇预告内存管理之后我们要探讨 C 中另一个“既迷人又危险”的特性。它让我们可以写出“生产代码的代码”让编译器为我们干活。➡️《你真的了解C吗》No.017模板元编程的黑魔法 (The Magic of Template Metaprogramming): SFINAE 与 Concept。