c++ shared_ptr与unique_ptr总结

unique_ptr

基本概念

std::unique_ptr<T> 是独占式智能指针:

  • 独占对象所有权,不可拷贝;
  • 可移动(C++11);
  • 离开作用域时自动删除所管理对象;
  • 指针唯一,适合资源严格独占场景。

底层原理

特性:

  • 内部只有一个裸指针 T* ptr;
  • 不需要引用计数
  • 拥有者离开作用域时调用 delete 或自定义 deleter

结构示意:

cpp 复制代码
template<class T, class Deleter = std::default_delete<T>>
class unique_ptr {
private:
    T* ptr;
    Deleter del;
};

删除动作:

cpp 复制代码
~unique_ptr() {
    if (ptr) del(ptr);
}

典型用法

  • 创建

    auto p = std::make_unique<int>(10);

  • 移动所有权

    std::unique_ptr<int> p1 = std::make_unique<int>(5);
    std::unique_ptr<int> p2 = std::move(p1);

  • 自定义删除器

    std::unique_ptr<FILE, decltype(&fclose)> fp(fopen("a.txt","r"), &fclose);

使用场景

std::unique_ptr 的核心是 独占所有权,适合代表"资源严格只有一个拥有者"的场景。

只要不是多个对象共享所有权,就应该优先使用 unique_ptr

它是默认、最安全、性能最佳的智能指针。

示例:unique_ptr 用法

cpp 复制代码
#include <iostream>
#include <memory>

struct Foo {
    Foo()  { std::cout << "Foo()\n"; }
    ~Foo() { std::cout << "~Foo()\n"; }
};

int main() {
    std::unique_ptr<Foo> p1 = std::make_unique<Foo>();

    // 转移所有权
    std::unique_ptr<Foo> p2 = std::move(p1);

    if (!p1) std::cout << "p1 is null\n";
}

输出:

复制代码
Foo()
p1 is null
~Foo()

shared_ptr

基本概念

std::shared_ptr<T> 是共享所有权智能指针:

  • 多个 smart pointer 可指向同一对象;
  • 使用引用计数计管理资源生命周期;
  • 最后一个 shared_ptr 消失时才释放资源。

底层原理

数据结构

shared_ptr 中含有两个关键对象:

  1. 控制块(control block) 包含:
  • use_count(引用计数)
  • weak_count
  • 删除器 Deleter
  • 分配器 Allocator
  • 指向对象的指针
  1. shared_ptr 内部只有两个指针
cpp 复制代码
T* ptr;                // 指向对象
ControlBlock* ctrl;    // 指向控制块

创建方式

推荐:make_shared

cpp 复制代码
auto p = std::make_shared<int>(10);

优点:

  • 对象和控制块在同一块内存
  • 更少的内存分配
  • 更高的缓存局部性
  • 更安全(异常安全)

拷贝/赋值:引用计数 +1

cpp 复制代码
auto a = std::make_shared<int>(5);
auto b = a; // use_count = 2

离开作用域:引用计数 -1

引用计数变为 0 时执行删除器:

cpp 复制代码
~shared_ptr() {
    if (--ctrl->use_count == 0) {
        del(ptr);
    }
}

示例:shared_ptr 引用计数演示

cpp 复制代码
#include <iostream>
#include <memory>

int main() {
    std::shared_ptr<int> p1 = std::make_shared<int>(42);
    std::cout << p1.use_count() << "\n"; // 1

    {
        std::shared_ptr<int> p2 = p1;
        std::cout << p1.use_count() << "\n"; // 2
    }

    std::cout << p1.use_count() << "\n"; // 1
}

unique_ptr VS shared_ptr

特性 unique_ptr shared_ptr
所有权 独占 共享
拷贝 不可
移动
内存开销 小(仅一个指针) 大(含控制块)
生命周期 自动,但唯一 引用计数控制
性能 更快 较慢(原子操作)
适用场景 独占资源 多模块共享资源
相关推荐
ALex_zry4 分钟前
C++20/23标准对进程间共享信息的优化:从传统IPC到现代C++的演进
开发语言·c++·c++20
郝学胜-神的一滴20 分钟前
深入解析Linux的`pthread_create`函数:从原理到实践
linux·服务器·c++·程序人生
小年糕是糕手24 分钟前
【C/C++刷题集】string类(一)
开发语言·数据结构·c++·算法·leetcode
暗然而日章25 分钟前
C++基础:Stanford CS106L学习笔记 12 运算符重载
c++·笔记·学习
JAVA+C语言37 分钟前
C++ 继承与派生
开发语言·c++
Andyshengwx44 分钟前
图论 最小生成树 MST问题
c++·算法·图论
闻缺陷则喜何志丹1 小时前
【图论 拓扑排序 贪心 临项交换】P5603 小 C 与桌游 题解|普及+
c++·算法·图论·贪心·拓扑排序·洛谷·临项交换
闻缺陷则喜何志丹1 小时前
【图论 BFS染色 并集查找 】P3663 [USACO17FEB] Why Did the Cow Cross the Road III S|普及+
c++·算法·图论·染色法·宽度优先·并集查找
mmz12071 小时前
差分数组(c++)
c++·算法
xu_yule1 小时前
算法基础-图论基础
数据结构·c++·算法·图论·dfs·bfs·最小生成树