C++学习系列(8):智能指针

C++学习系列(8):智能指针

1. 引言

在 C++ 中,手动管理内存(使用 newdelete)很容易导致 内存泄漏悬空指针
为了解决这个问题,C++ 提供了 智能指针(Smart Pointer) 来自动管理内存,避免手动 delete 的麻烦。

本篇博客,我们将学习:

  • 智能指针的基本概念
  • std::unique_ptr(独占所有权)
  • std::shared_ptr(共享所有权)
  • std::weak_ptr(弱引用,避免循环引用)

2. 智能指针概述

C++11 引入了智能指针,它们位于 <memory> 头文件中:

智能指针特性适用场景
std::unique_ptr独占所有权资源只由一个指针管理
std::shared_ptr共享所有权允许多个指针共享同一资源
std::weak_ptr弱引用,不影响计数避免 shared_ptr 循环引用

3. std::unique_ptr(独占所有权)

特点

  • 一个对象只能由一个 unique_ptr 管理
  • 无法进行复制,但可以移动
  • 自动释放内存(无需手动 delete
#include <iostream>
#include <memory>

class MyClass {
public:
    MyClass() { std::cout << "构造 MyClass\n"; }
    ~MyClass() { std::cout << "析构 MyClass\n"; }
    void show() { std::cout << "Hello, unique_ptr!\n"; }
};

int main() {
    std::unique_ptr<MyClass> ptr = std::make_unique<MyClass>();
    ptr->show();

    // 不能复制,但可以转移所有权
    std::unique_ptr<MyClass> ptr2 = std::move(ptr);

    if (!ptr) std::cout << "ptr 已为空\n";

    return 0;
}

📌 解析

  • std::make_unique<MyClass>() 推荐创建 unique_ptr
  • unique_ptr 不能复制,但可使用 std::move 进行 所有权转移
  • 退出作用域时,自动释放内存

4. std::shared_ptr(共享所有权)

特点

  • 多个 shared_ptr 可以共享同一对象
  • 使用引用计数管理资源
  • 当最后一个 shared_ptr 释放时,资源被释放
#include <iostream>
#include <memory>

class MyClass {
public:
    MyClass() { std::cout << "构造 MyClass\n"; }
    ~MyClass() { std::cout << "析构 MyClass\n"; }
    void show() { std::cout << "Hello, shared_ptr!\n"; }
};

int main() {
    std::shared_ptr<MyClass> ptr1 = std::make_shared<MyClass>();
    std::cout << "引用计数: " << ptr1.use_count() << std::endl;

    std::shared_ptr<MyClass> ptr2 = ptr1;  // 共享所有权
    std::cout << "引用计数: " << ptr1.use_count() << std::endl;

    return 0;
}

📌 解析

  • std::make_shared<T>() 高效分配内存
  • use_count() 获取 引用计数
  • 引用计数归零时,自动释放内存

5. std::weak_ptr(防止循环引用)

为什么需要 weak_ptr

如果 AB 互相持有 shared_ptr,它们的引用计数永远不会归零,导致 内存泄漏(循环引用)。

解决方案

  • 使用 std::weak_ptr 弱引用,不会增加引用计数
  • weak_ptr 需要转换为 shared_ptr 才能使用
#include <iostream>
#include <memory>

class B;  // 先声明 B

class A {
public:
    std::shared_ptr<B> ptrB;
    ~A() { std::cout << "A 被析构\n"; }
};

class B {
public:
    std::weak_ptr<A> ptrA;  // 使用 weak_ptr 解决循环引用
    ~B() { std::cout << "B 被析构\n"; }
};

int main() {
    std::shared_ptr<A> a = std::make_shared<A>();
    std::shared_ptr<B> b = std::make_shared<B>();

    a->ptrB = b;
    b->ptrA = a;  // 使用 weak_ptr 解决循环引用

    return 0;
}

📌 解析

  • weak_ptr 不会增加引用计数
  • weak_ptr.lock() weak_ptr 转换回 shared_ptr
  • 避免循环引用,防止内存泄漏

6. 智能指针对比总结

智能指针主要特点适用场景
unique_ptr独占所有权,不能复制资源只需单一管理者
shared_ptr共享所有权,引用计数资源被多个对象共享
weak_ptr不增加引用计数,防止循环引用解决 shared_ptr 循环依赖问题

7. 什么时候使用智能指针?

适合使用智能指针的场景

  • 需要 动态分配 内存,并自动管理资源
  • 资源只属于一个对象unique_ptr
  • 资源被多个对象共享shared_ptr
  • 需要防止 shared_ptr 循环引用weak_ptr

🚫 不适合使用智能指针的场景

  • 栈对象(智能指针用于堆对象
  • 需要 显式控制对象生命周期 的场景
  • 性能敏感的地方(智能指针带有额外的开销)

8. 总结

std::unique_ptr:独占所有权,无法复制
std::shared_ptr:共享所有权,引用计数
std::weak_ptr:弱引用,避免 shared_ptr 循环引用

🎯 智能指针是 C++ 现代化开发的重要工具,推荐在合适的场景使用!

在下一篇 C++学习系列(9) 中,我们将深入学习 C++ 多线程编程,敬请期待!🚀


💡 如果你喜欢这篇文章,欢迎点赞、收藏,并关注本系列!

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值