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
所有权 独占 共享
拷贝 不可
移动
内存开销 小(仅一个指针) 大(含控制块)
生命周期 自动,但唯一 引用计数控制
性能 更快 较慢(原子操作)
适用场景 独占资源 多模块共享资源
相关推荐
.小墨迹1 小时前
apollo学习之借道超车的速度规划
linux·c++·学习·算法·ubuntu
历程里程碑2 小时前
Linux20 : IO
linux·c语言·开发语言·数据结构·c++·算法
郝学胜-神的一滴2 小时前
深入浅出:使用Linux系统函数构建高性能TCP服务器
linux·服务器·开发语言·网络·c++·tcp/ip·程序人生
天若有情6732 小时前
【自研实战】轻量级ASCII字符串加密算法:从设计到落地(防查岗神器版)
网络·c++·算法·安全·数据安全·加密
czy87874752 小时前
深入了解 C++ 中的 `std::bind` 函数
开发语言·c++
我在人间贩卖青春3 小时前
C++之继承的方式
c++·private·public·protected·继承方式
智者知已应修善业4 小时前
【洛谷P9975奶牛被病毒传染最少数量推导,导出多样例】2025-2-26
c语言·c++·经验分享·笔记·算法·推荐算法
Trouvaille ~4 小时前
【Linux】应用层协议设计实战(一):自定义协议与网络计算器
linux·运维·服务器·网络·c++·http·应用层协议
CSCN新手听安4 小时前
【linux】高级IO,I/O多路转接之poll,接口和原理讲解,poll版本的TCP服务器
linux·运维·服务器·c++·计算机网络·高级io·poll
CSCN新手听安4 小时前
【linux】网络基础(三)TCP服务端网络版本计算器的优化,Json的使用,服务器守护进程化daemon,重谈OSI七层模型
linux·服务器·网络·c++·tcp/ip·json