首页 > 编程语言 >C++ 智能指针详解: std::unique_ptr 和 std::shared_ptr

C++ 智能指针详解: std::unique_ptr 和 std::shared_ptr

时间:2024-09-27 18:13:42浏览次数:5  
标签:std C++ ptr1 shared unique ptr 指针

C++11引入了智能指针,它们是管理动态分配内存的强大工具。本文将详细介绍两种最常用的智能指针: std::unique_ptrstd::shared_ptr

std::unique_ptr

概述

std::unique_ptr 是一种独占所有权的智能指针。它确保一个对象只能被一个 unique_ptr 所拥有,这意味着不能复制 unique_ptr,只能移动它。

主要特性

  1. 独占所有权: 一个 unique_ptr 不能被复制,只能被移动。
  2. 自动释放: 当 unique_ptr 离开作用域时,它所管理的对象会被自动删除。
  3. 零开销: 在大多数操作中, unique_ptr 与原始指针的性能相当。
  4. 自定义删除器: 可以指定自定义的删除方式。

示例代码

#include <iostream>
#include <memory>

class MyClass {
public:
    MyClass() { std::cout << "MyClass constructed\n"; }
    ~MyClass() { std::cout << "MyClass destructed\n"; }
    void doSomething() { std::cout << "Doing something\n"; }
};

int main() {
    // 创建unique_ptr
    std::unique_ptr<MyClass> ptr1 = std::make_unique<MyClass>();
    
    // 使用->访问成员
    ptr1->doSomething();
    
    // 无法复制unique_ptr
    // std::unique_ptr<MyClass> ptr2 = ptr1; // 编译错误
    
    // 可以移动unique_ptr
    std::unique_ptr<MyClass> ptr2 = std::move(ptr1);
    
    // ptr1现在为空
    if (ptr1 == nullptr) {
        std::cout << "ptr1 is null\n";
    }
    
    // ptr2现在拥有对象
    ptr2->doSomething();
    
    // 离开作用域时,ptr2自动删除对象
}

std::shared_ptr

概述

std::shared_ptr 是一种共享所有权的智能指针。多个 shared_ptr 可以指向同一个对象,对象的内存会在最后一个引用被销毁时释放。

主要特性

  1. 共享所有权: 多个 shared_ptr 可以指向同一个对象。
  2. 引用计数: 内部维护一个引用计数,当计数降为0时删除对象。
  3. 线程安全: 引用计数的增减是原子操作,但对象本身的访问不是线程安全的。
  4. 可以从 this 指针创建: 可以安全地从一个对象的成员函数中创建指向 this 的 shared_ptr

示例代码

#include <iostream>
#include <memory>

class SharedClass : public std::enable_shared_from_this<SharedClass> {
public:
    SharedClass() { std::cout << "SharedClass constructed\n"; }
    ~SharedClass() { std::cout << "SharedClass destructed\n"; }
    
    std::shared_ptr<SharedClass> getShared() {
        return shared_from_this();
    }
};

int main() {
    // 创建shared_ptr
    auto ptr1 = std::make_shared<SharedClass>();
    
    {
        // 创建另一个指向同一对象的shared_ptr
        std::shared_ptr<SharedClass> ptr2 = ptr1;
        
        std::cout << "使用计数: " << ptr1.use_count() << std::endl; // 输出 2
        
        // 从对象内部获取shared_ptr
        auto ptr3 = ptr1->getShared();
        std::cout << "使用计数: " << ptr1.use_count() << std::endl; // 输出 3
        
        // ptr2和ptr3离开作用域,但对象不会被删除
    }
    
    std::cout << "使用计数: " << ptr1.use_count() << std::endl; // 输出 1
    
    // ptr1离开作用域,对象被删除
}

比较 unique_ptr 和 shared_ptr

特性 std::unique_ptr std::shared_ptr
所有权 独占 共享
复制 不允许 允许
移动 允许 允许
引用计数
性能开销 几乎为零 有一定开销
内存使用 与原始指针相同 额外内存用于控制块
线程安全 不适用 引用计数操作是安全的
循环引用 不会发生 可能发生,需要注意

最佳实践

  1. 优先使用 std::unique_ptr,除非确实需要共享所有权。
  2. 使用 std::make_uniquestd::make_shared 来创建智能指针。
  3. 避免使用裸指针,尽可能使用智能指针。
  4. 注意避免 std::shared_ptr 的循环引用问题,必要时使用 std::weak_ptr
  5. 在类的公共接口中返回 std::unique_ptr 来转移所有权。
  6. 在需要共享但不参与所有权的场景中使用 std::weak_ptr

std::unique_ptrstd::shared_ptr 是C++中管理动态内存的强大工具。正确使用这些智能指针可以大大减少内存泄漏的风险,提高代码的安全性和可维护性。理解它们的特性和适用场景对于编写高质量的C++程序至关重要。

标签:std,C++,ptr1,shared,unique,ptr,指针
From: https://www.cnblogs.com/linxmouse/p/18436318

相关文章

  • C++17 std::variant 详解:概念、用法和实现细节
    std::variant是C++17引入的一个新的标准库类型,它提供了一种类型安全的联合体。这个类可以在同一时间持有几种可能类型中的一个值。本文将详细介绍std::variant的概念、用法和实现细节。1.基本概念std::variant是一个模板类,可以存储几种不同类型中的一个值。它的声明如下:te......
  • 地平线静态目标检测 MapTR 参考算法-V1.0
    1.简介高清地图是自动驾驶系统的重要组件,提供精确的驾驶环境信息和道路语义信息。传统离线地图构建方法成本高,维护复杂,使得依赖车载传感器的实时感知建图成为新趋势。早期实时建图方法存在局限性,如处理复杂地图元素的能力不足、缺乏实例级信息等,在实时性和后处理复杂度上存在挑战......
  • C++离线查询
    前言C++算法与数据结构打开打包代码的方法兼述单元测试概念及原理离线算法(offlinealgorithms),离线计算就是在计算开始前已知所有输入数据,输入数据不会产生变化,且在解决一个问题后就要立即得出结果的前提下进行的计算。通俗的说:离线查询:问完所有问题后,依次回答。可......
  • 软件工程结队项目:基于C++实现的自动生成小学四则运算的命令行程序
    这个作业属于哪个课程https://edu.cnblogs.com/campus/gdgy/CSGrade22-34这个作业要求在哪里https://edu.cnblogs.com/campus/gdgy/CSGrade22-34/homework/13230这个作业的目标<运用C++实现四则运算法则的命令行程序>团队成员1李梓灏3122004695团队成员2吴......
  • 【C++进阶】AVL树的介绍及实现
    【C++进阶】AVL树的介绍及实现......
  • C++顺序结构(2)学习任务
    在坚果云中注册免费个人云盘一、视频下载存放在规划好的文件夹中,并观看学习1、变量存储.注释2、四则运算.输入3、认识设置DEV-C++4、第一个C++程序5、头文件6、命名空间7、cout语句8、什么是变量?9、表达式和赋值语句10、计数器11、自加自减运算符12、课后题目113、......
  • C++-练习-45
    题目:下面是一个结构声明:structbox{        charmaker[40];        floatheight;        floatwidth;        floatlength;        floatvolume;};编写一个函数,按值传递box结构,并显示每个成员的值。编写一个函数,传......
  • 【C++篇】从零实现 C++ Vector:深度剖析 STL 的核心机制与优化
    文章目录从零实现C++Vector前言1.基本结构与初始化细分1.1空构造函数的实现与测试实现代码:测试用例:输出:1.2带大小和默认值的构造函数实现代码:测试用例:输出:1.3拷贝构造函数实现代码:测试用例:输出:1.4赋值操作符的实现实现代码:测试用例:输出:2.容量管理的实现与测......
  • C++ 标准模板库(STL)之集合(set)
    啊,哈喽,小伙伴们大家好。我是#张亿,今天呐,学的n钱买n鸡是集合(set)C++标准模板库(STL)之集合(set)(下面代码中的std::要去掉)在C++标准模板库(STL)中,set 是一种非常有用的容器,用于存储唯一元素的集合。set 内部自动对元素进行排序,通常使用红黑树(Red-BlackTree)实现,以保证元素以升......
  • C++ 文件I/O流
    C++文件的I/O流一、c++对文本文件的读写a.创建流对象,通过流对象打开文件ofstreamofs(constchar*filename,openmodemode);b.通过成员函数方式,打开文件voidopen(constchar*filename);voidopen(constchar*filename,openmodemode);filename:文件的路径mode:打开......