C++一分钟之-智能指针:unique_ptr与shared_ptr

本文涉及的产品
大数据开发治理平台 DataWorks,不限时长
实时数仓Hologres,5000CU*H 100GB 3个月
实时计算 Flink 版,5000CU*H 3个月
简介: 【6月更文挑战第24天】C++智能指针`unique_ptr`和`shared_ptr`管理内存,防止泄漏。`unique_ptr`独占资源,离开作用域自动释放;`shared_ptr`通过引用计数共享所有权,最后一个副本销毁时释放资源。常见问题包括`unique_ptr`复制、`shared_ptr`循环引用和裸指针转换。避免这些问题需使用移动语义、`weak_ptr`和明智转换裸指针。示例展示了如何使用它们管理资源。正确使用能提升代码安全性和效率。

智能指针是C++中用于自动管理内存的工具,它们通过模拟拥有所有权的对象来防止内存泄漏,其中unique_ptrshared_ptr是最常用的两种类型。本文将深入探讨这两种智能指针的工作原理、应用场景、常见问题、易错点及避免策略,并通过具体代码示例加以说明。
image.png

unique_ptr与shared_ptr概览

unique_ptr

unique_ptr表示独占所有权的智能指针,同一时间内只能有一个unique_ptr指向给定的资源。当unique_ptr离开作用域时,它所管理的资源会被自动释放。这种设计保证了资源的唯一性和确定性释放。

shared_ptr

shared_ptr允许多个智能指针共享同一个资源的所有权。它通过引用计数来追踪有多少个shared_ptr指向同一资源,当最后一个指向该资源的shared_ptr销毁时,资源被释放。这使得shared_ptr非常适合于复杂数据结构的共享和跨组件传递。

常见问题与易错点

误用unique_ptr共享资源

尝试复制unique_ptr会导致编译错误,因为它是独占所有权的。试图通过值传递或赋值方式分享unique_ptr管理的资源是错误的。

循环引用导致的内存泄漏

使用shared_ptr时,如果不小心形成了循环引用(两个或多个shared_ptr互相引用形成闭环),即使所有指向它们的普通引用都已消失,它们的引用计数也不会降为零,从而导致资源无法释放,引发内存泄漏。

忽略裸指针转换

从原始指针到智能指针的转换需谨慎,特别是当原始指针已被其他地方管理时,直接构造智能指针可能会导致重复释放资源。

如何避免这些问题

使用转移语义避免unique_ptr误用

利用unique_ptr的移动语义(move semantics),而非拷贝,来传递资源的所有权。

破坏循环引用

  • 使用weak_ptr:当不需要增加引用计数时,使用weak_ptr来监视shared_ptr而不增加其引用计数,可以打破潜在的循环引用。
  • 重新设计数据结构:避免不必要的相互引用,或使用其他设计模式(如观察者模式)来替代直接的相互持有。

明智地转换裸指针

  • 在将裸指针转换为智能指针之前,确保该指针未被其他智能指针管理。
  • 使用make_shared来创建shared_ptr,以减少潜在的内存分配次数和提高效率。

代码示例

unique_ptr示例

#include <memory>

void manageResource(std::unique_ptr<int> ptr) {
   
   
    // 使用资源
} // ptr在此处自动销毁,资源被释放

int main() {
   
   
    auto ptr = std::make_unique<int>(42); // 创建并初始化unique_ptr
    manageResource(std::move(ptr)); // 移动所有权到函数内
    // ptr现在为空,资源已在manageResource内部被释放
    return 0;
}

shared_ptr与weak_ptr示例

#include <memory>

class Node {
   
   
public:
    std::shared_ptr<Node> next;
    std::weak_ptr<Node> prev;
    // ...其他成员和方法
};

void createChain() {
   
   
    auto node1 = std::make_shared<Node>();
    auto node2 = std::make_shared<Node>();

    node1->next = node2;
    node2->prev = node1; // 使用weak_ptr避免循环引用
}

int main() {
   
   
    createChain();
    // 所有资源在离开作用域时将被正确释放,无内存泄漏风险
    return 0;
}

总结

unique_ptrshared_ptr是C++智能指针家族中的两大支柱,它们各自适用于不同的场景。正确使用它们不仅能够有效避免内存泄漏,还能简化资源管理,提升代码的安全性和可维护性。通过了解它们的工作原理、识别常见问题和易错点,并采取相应的避免策略,开发者可以更加高效地利用智能指针的强大功能,构建高质量的C++应用程序。

目录
相关文章
|
3天前
|
存储 安全 编译器
【C++航海王:追寻罗杰的编程之路】引用、内联、auto关键字、基于范围的for、指针空值nullptr
【C++航海王:追寻罗杰的编程之路】引用、内联、auto关键字、基于范围的for、指针空值nullptr
32 5
|
2天前
|
C++ 容器
【编程技巧】 C++11智能指针
C++11引入了智能指针以自动管理内存,防止内存泄漏和悬挂指针: - `shared_ptr`:引用计数,多所有权,适用于多个对象共享资源。 - `unique_ptr`:独占所有权,更轻量级,适用于单一对象所有者。 - `weak_ptr`:弱引用,不增加引用计数,解决`shared_ptr`循环引用问题。 ## shared_ptr - 支持引用计数,所有者共同负责资源释放。 - 创建方式:空指针、new操作、拷贝构造/移动构造,以及自定义删除器。 - 提供`operator*`和`operator-&gt;`,以及`reset`、`swap`等方法。 ## unique_ptr
|
4天前
|
存储 Java C#
C++语言模板类对原生指针的封装与模拟
C++|智能指针的智能性和指针性:模板类对原生指针的封装与模拟
|
2天前
|
C++
C++职工管理系统(类继承、文件、指针操作、中文乱码解决)
C++职工管理系统(类继承、文件、指针操作、中文乱码解决)
4 0
C++职工管理系统(类继承、文件、指针操作、中文乱码解决)
|
2天前
|
C++
C++指针
C++指针
4 0
|
3天前
|
安全 编译器 C++
【C++】学习笔记——类和对象_5
【C++】学习笔记——类和对象_5
17 9
|
3天前
|
编译器 C++
【C++】学习笔记——类和对象_4
【C++】学习笔记——类和对象_4
14 6
|
3天前
|
存储 编译器 C++
【C++】学习笔记——类和对象_3
【C++】学习笔记——类和对象_3
17 6
|
3天前
|
存储 编译器 C语言
【C++】学习笔记——类和对象_2
【C++】学习笔记——类和对象_2
14 3
|
3天前
|
存储 编译器 C语言
【C++航海王:追寻罗杰的编程之路】类与对象你学会了吗?(上)
【C++航海王:追寻罗杰的编程之路】类与对象你学会了吗?(上)
8 2