C++智能指针超萌新指南:会呼吸的内存管家

基础能力

看智能指针,需要你先学会指针!

【C++指针完全解读】新手也能玩转的“内存地图“导航手册-CSDN博客

🎈 一、智能指针是什么?

想象你养了一只电子宠物(内存对象),每次忘记喂食(释放内存)它就会饿死(内存泄漏)。智能指针就像自动喂食器,帮你记住何时该清理内存!

传统指针的痛点

int* pet = new int(5);  // 领养宠物
// ...中间可能忘记写 delete...
// 宠物饿死了 QAQ

 

智能指针救星

#include <memory>
auto smart_pet = std::make_unique<int>(5); 
// 不用手动delete!离开作用域自动清理

 


🧩 二、三大智能指针详解

1. unique_ptr:专属管家

特点

  • 唯一主人(不能复制)

  • 轻量高效(接近裸指针)

  • 离开作用域自动释放

代码全解

// 创建方式(C++14推荐make_unique)
auto cat = std::make_unique<std::string>("Tom"); 

// 转移所有权(原指针变空)
auto new_owner = std::move(cat);  

// 错误示例:
// auto copy = cat;  // 编译报错!禁止复制

// 手动释放(一般不需要!)
new_owner.reset();  // 等同于delete操作

 

2. shared_ptr:共享家庭

特点

  • 多人共享(引用计数)

  • 计数为0时自动清理

  • 稍重(维护计数开销)

代码全解

// 创建方式(优先用make_shared)
auto dog = std::make_shared<std::string>("Bobby");

// 复制增加计数
auto family_member1 = dog;  // 计数+1 → 2
{
    auto family_member2 = dog;  // 计数+1 → 3
} // 成员2离开,计数-1 → 2

// 查看当前计数(调试用)
std::cout << dog.use_count();  // 输出2

// 手动释放(不推荐!)
dog.reset();  // 计数-1 → 1(若计数为0才释放内存)

 

3. weak_ptr:安全观察员

特点

  • 不增加引用计数

  • 解决循环引用问题

  • 必须通过lock()获取临时使用权

代码全解

// 创建方式(从shared_ptr转换)
auto rabbit = std::make_shared<int>(10);
std::weak_ptr<int> weak_rabbit = rabbit;  

// 尝试访问(安全!)
if (auto temp = weak_rabbit.lock()) { 
    std::cout << *temp;  // 访问成功
} else {
    std::cout << "对象已销毁"; 
}

// 典型应用场景:打破循环引用
struct Node {
    // std::shared_ptr<Node> parent;  // ❌ 循环引用
    std::weak_ptr<Node> parent;       // ✅ 正确方式
};

 


🚨 三、避坑大作战

坑1:混合使用原始指针
int* raw = new int(20);
std::shared_ptr<int> sp1(raw);  // 正确
// std::shared_ptr<int> sp2(raw); // 灾难!重复释放

 

正确做法

auto sp1 = std::make_shared<int>(20);  // 从开始就用智能指针

 

坑2:返回智能指针的裸指针

auto sp = std::make_shared<int>(30);
int* dangerous = sp.get();  
delete dangerous;  // 导致双重释放!

 

牢记.get()获得的指针只能观察,不能delete!

坑3:循环引用
struct A {
    std::shared_ptr<B> b_ptr;  
};
struct B {
    std::shared_ptr<A> a_ptr;  // 互相持有→内存泄漏!
};

 

解决方案

struct B {
    std::weak_ptr<A> a_ptr;  // 改用weak_ptr
};

 


🗺️ 四、选择指针的决策图

是否需要共享对象?
├── 否 → 用unique_ptr(默认首选)
└── 是 → 是否可能循环引用?
    ├── 否 → 用shared_ptr  
    └── 是 → 组合使用shared_ptr + weak_ptr

💡 五、性能小贴士

  1. 优先用make_xxx

    // 更好:单次内存分配(对象+控制块)
    auto sp = std::make_shared<MyClass>(args);  
    
    // 较差:两次分配(可能引发内存碎片)
    std::shared_ptr<MyClass> sp(new MyClass(args));

  • 避免大量shared_ptr拷贝

    void process(const std::shared_ptr<Object>& obj);  // 传引用避免计数操作

    unique_ptr性能几乎无损耗:可放心替代裸指针!


🌈 结语
智能指针不是魔法,但能让你的代码:
✅ 减少80%内存相关bug
✅ 更易读和维护
✅ 安全地拥抱C++的强大能力

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

北岭敲键盘的荒漠猫

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值