跳到主要内容
极客日志极客日志
首页博客AI提示词GitHub精选代理工具
搜索
|注册
博客列表
C++算法

C++ 智能指针详解:原理、实现与使用

C++ 智能指针基于 RAII 思想封装动态内存,自动管理生命周期。主要类型包括 auto_ptr(已废弃)、unique_ptr(独占所有权)、shared_ptr(引用计数共享)及 weak_ptr(解决循环引用)。通过重载操作符模拟指针行为,配合删除定制器处理特殊释放逻辑,有效避免内存泄漏和重复释放问题。

接口猎人发布于 2026/3/16更新于 2026/5/37 浏览
C++ 智能指针详解:原理、实现与使用

前言

在 C++ 编程中,动态内存管理始终是开发者面临的核心挑战之一。手动使用 new 分配内存、delete 释放内存的模式,不仅需要开发者时刻关注内存生命周期,更可能因疏忽导致内存泄漏(忘记调用 delete)、二次释放(重复调用 delete),或是在异常抛出时因执行流跳转跳过 delete 语句等问题 —— 这些隐患轻则导致程序性能退化,重则引发崩溃或不可预期的运行错误。

为解决这一痛点,C++ 标准库引入了智能指针这一核心工具。它基于'资源获取即初始化'(RAII)的设计思想,将动态内存资源封装为对象的成员,利用 C++ 对象自动调用析构函数的特性,实现内存的'自动释放',从根本上减少手动管理内存的负担与风险。

本文将系统梳理智能指针的核心作用、实现原理,并针对 C++ 标准库中不同类型的智能指针(auto_ptr、unique_ptr、shared_ptr、weak_ptr)展开详细解析:包括它们的设计逻辑、模拟实现代码、适用场景,以及如何规避 shared_ptr 循环引用等典型问题。同时,文中还将补充'删除定制器'等进阶用法,帮助开发者根据实际需求灵活应对复杂的内存管理场景。

智能指针的作用

作用:如果正确使用了智能指针的话,就不用自己手动 delete 了。

自己手动 delete 容易忽略的地方:在抛异常时容易跳过自己写的 delete 或者自己忘记 delete 了。

智能指针的实现和原理

原理:资源交给对象管理,对象生命周期内,资源有效;对象生命周期到了,释放资源——用的是 RAII 思想。

在实现的时候要让这个对象的用法像指针一样。

template <class T>
class SmartPtr {
public:
    SmartPtr(T* ptr) : _ptr(ptr) {}
    ~SmartPtr() { delete _ptr; }
    T& operator*() { return *_ptr; }
    T* operator->() { return _ptr; }
private:
    T* _ptr;
};

但是这种智能指针有个问题:所有权转移后原指针失效,且不支持拷贝构造时的深拷贝保护。

库里面的智能指针

不需要拷贝的场景,一般使用 unique_ptr。

需要拷贝的场景,一般使用 shared_ptr——但是要小心循环引用。

std::auto_ptr

这个是 C++98 实现的,原理其实就是管理权的转移。例如在拷贝时,会把被拷贝对象的资源管理权转移给拷贝对象,被拷贝对象悬空。

这个智能指针也是基于 RAII 思想搞出来的。

这个智能指针有很大的弊端:如果管理权被转移了的话,之前那个指针就会变成空指针。

因此很多公司都是明令禁止使用的。

auto_ptr 的模拟实现
template <class T>
class auto_ptr {
public:
    (T* ptr) : _ptr(ptr) {}
    ~() {  _ptr; }
    T& *() {  *_ptr; }
    T* ->() {  _ptr; }
    (auto_ptr<T>& ap) : _ptr(ap._ptr) { ap._ptr = ; }
    
:
    T* _ptr;
};

auto_ptr
auto_ptr
delete
operator
return
operator
return
auto_ptr
nullptr
// 其实还有=号,-> 会把 eg: sp1 = sp2 的 sp1 原来的内存 delete 掉,然后管理权转移
private
// 使用 eg:A 是一个类 auto_ptr<A>ap1(new A(5));

std::unique_ptr

unique_ptr、shared_ptr 和 weak_ptr 是 Boost 库先实现的 (底层和名字稍有不同),后来 C++11 也支持这几个智能指针的使用了。

unique_ptr 的话就是直接让智能指针不能拷贝和赋值 + 管理权转移。

这个智能指针也是基于 RAII 思想实现的。

unique_ptr 的模拟实现
template <class T>
class unique_ptr {
public:
    unique_ptr(T* ptr) : _ptr(ptr) {}
    ~unique_ptr() { delete _ptr; }
    T& operator*() { return *_ptr; }
    T* operator->() { return _ptr; }
    unique_ptr(unique_ptr<T>& ap) = delete;
    unique_ptr<T>& operator=(unique_ptr<T>& ap) = delete;
    // 除了这种办法:还能 private 这个成员函数,并且只声明不实现
private:
    T* _ptr;
};
// 使用:unique_ptr<A>up1(new A(5));

引申:一般拷贝不让实现的话,赋值也不能实现——就像上面禁止就一起禁止了。

std::shared_ptr

这个智能指针是最全面的——一般都是用的这个,然后有循环引用的时候搭配 weak_ptr 用。

也是 RAII 思想实现的。

原理:通过引用计数的方式来实现多个 shared_ptr 对象之间共享资源。

shared_ptr 的模拟实现
template <class T>
class shared_ptr {
public:
    shared_ptr(T* ptr = nullptr) : _ptr(ptr), _pcount(new int(1)) {}
    template <class D>
    shared_ptr(T* ptr, D del) : _ptr(ptr), _pcount(new int(1)), _del(del) {}
    ~shared_ptr() {
        if (--(*_pcount) == 0) {
            _del(_ptr);
            delete _pcount;
        }
    }
    T& operator*() { return *_ptr; }
    T* operator->() { return _ptr; }
    shared_ptr(const shared_ptr<T>& sp) : _ptr(sp._ptr), _pcount(sp._pcount) {
        ++(*_pcount);
    }
    shared_ptr<T>& operator=(const shared_ptr<T>& sp) {
        if (_ptr == sp._ptr) return *this;
        if (--(*_pcount) == 0) {
            delete _ptr;
            delete _pcount;
        }
        _ptr = sp._ptr;
        _pcount = sp._pcount;
        ++(*_pcount);
        return *this;
    }
    T* get() const { return _ptr; }
private:
    T* _ptr;
    int* _pcount;
    function<void(T*)> _del = [](T* ptr){delete ptr;};
};
// 用法:shared_ptr<A>sp1(new A(1));注意:shared_ptr<A>跟 A 可不是一个类型

引申:编译器对越界访问的检查一般不是很彻底的。

shared_ptr 的一个弊端

shared_ptr 在遇到循环引用的时候也是会内存泄漏的。

std::weak_ptr

weak_ptr 这个智能指针不是 RAII 思想的,他的唯一作用就是解决 shared_ptr 的循环引用问题的。

这个智能指针可以访问资源,但是不参与资源释放的解决。

weak_ptr 不能管理资源!!!

注意:weak_ptr 库里面实现了让他可以和 shared_ptr 相互转换。

weak_ptr 的模拟实现
template <class T>
class weak_ptr {
public:
    weak_ptr() : _ptr(nullptr) {}
    weak_ptr(const shared_ptr<T>& sp) : _ptr(sp.get()) {}
    weak_ptr<T>& operator=(const shared_ptr<T>& sp) {
        _ptr = sp.get();
        return *this;
    }
    T& operator*() { return *_ptr; }
    T* operator->() { return _ptr; }
private:
    T* _ptr;
};
// weak_ptr 其实也是可以转换成 shared_ptr 的,只是自己没有实现罢了

删除定制器

在智能指针使用过程中,可能会有 new[] 或者 malloc 出来的空间,这些空间用 delete 根本不行——此时就需要删除定制器了。

库里面的话,是给 unique_ptr 和 shared_ptr 配备了删除定制器的。

这里的话,自己模拟实现一下 shared_ptr 的删除定制器 (在上面的模拟实现里面自己写了的)。

目录

  1. 前言
  2. 智能指针的作用
  3. 智能指针的实现和原理
  4. 库里面的智能指针
  5. std::auto_ptr
  6. auto_ptr 的模拟实现
  7. std::unique_ptr
  8. unique_ptr 的模拟实现
  9. std::shared_ptr
  10. shared_ptr 的模拟实现
  11. shared_ptr 的一个弊端
  12. std::weak_ptr
  13. weak_ptr 的模拟实现
  14. 删除定制器
  • 💰 8折买阿里云服务器限时8折了解详情
  • GPT-5.5 超高智商模型1元抵1刀ChatGPT中转购买
  • 代充Chatgpt Plus/pro 帐号了解详情
  • 🤖 一键搭建Deepseek满血版了解详情
  • 一键打造专属AI 智能体了解详情
极客日志微信公众号二维码

微信扫一扫,关注极客日志

微信公众号「极客日志V2」,在微信中扫描左侧二维码关注。展示文案:极客日志V2 zeeklog

更多推荐文章

查看全部
  • n8n 自动化工作流平台部署与实战指南
  • Linux 下 Git 入门:高效管理代码库实战指南
  • Claude AI 母公司更新服务条款:中国地区及公司受限访问
  • 巅峰对决:Codex Multi-Agent vs Claude Agent Teams,谁才是最强 AI 编程团队?
  • SpringBoot 整合 Zookeeper 常见错误总结
  • 医疗 AI 场景下的模型融合与集成策略深度解析
  • OpenClaw 开源 AI 智能体框架更新与核心功能解析
  • Unity 集成 Whisper 实现本地离线语音识别
  • C++ unordered 系列容器使用与底层模拟实现
  • LIBERO 数据集:终身机器人学习与知识迁移基准
  • 2026 年 3 月 GESP C++ 一级真题及解析:数字替换
  • Windows VSCode 配置 MinGW 与手动编译安装 OpenCV 实战
  • 零基础入门网络安全学习指南
  • SpringAI 通过 Ollama 本地部署 Deepseek 模型实现对话机器人
  • Python 路径拼接实战:os.path.join() 函数用法详解
  • Openclaw 与飞书多机器人配置指南
  • LeetCode 49. 字母异位词分组:两种高效 C++ 解法
  • OpenClaw 接入自定义模型与 WebUI 智能操作指南
  • Redis 7 持久化机制详解:RDB 与 AOF 原理
  • System Verilog 核心教程:从基础语法到验证架构

相关免费在线工具

  • 加密/解密文本

    使用加密算法(如AES、TripleDES、Rabbit或RC4)加密和解密文本明文。 在线工具,加密/解密文本在线工具,online

  • Gemini 图片去水印

    基于开源反向 Alpha 混合算法去除 Gemini/Nano Banana 图片水印,支持批量处理与下载。 在线工具,Gemini 图片去水印在线工具,online

  • Base64 字符串编码/解码

    将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online

  • Base64 文件转换器

    将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online

  • Markdown转HTML

    将 Markdown(GFM)转为 HTML 片段,浏览器内 marked 解析;与 HTML转Markdown 互为补充。 在线工具,Markdown转HTML在线工具,online

  • HTML转Markdown

    将 HTML 片段转为 GitHub Flavored Markdown,支持标题、列表、链接、代码块与表格等;浏览器内处理,可链接预填。 在线工具,HTML转Markdown在线工具,online