0

0

现代C++中的智能指针有哪些区别 unique_ptr shared_ptr weak_ptr对比

P粉602998670

P粉602998670

发布时间:2025-07-07 08:01:02

|

191人浏览过

|

来源于php中文网

原创

智能指针是c++++中自动管理内存的工具,主要包括unique_ptr、shared_ptr和weak_ptr。1. unique_ptr用于独占所有权,不可复制,转移需用std::move,销毁时自动删除对象;2. shared_ptr允许多个指针共享同一对象,通过引用计数管理生命周期,但需注意循环引用问题;3. weak_ptr作为弱引用不增加引用计数,用于解决循环引用及实现缓存等场景。合理选择智能指针可避免内存泄漏并提升效率。

现代C++中的智能指针有哪些区别 unique_ptr shared_ptr weak_ptr对比

智能指针,说白了,就是帮你自动管理内存的指针。现代 C++ 里,它们已经是标配了,unique_ptrshared_ptrweak_ptr,各有各的用处和侧重点,用错了地方,轻则效率打折,重则内存泄漏。

现代C++中的智能指针有哪些区别 unique_ptr shared_ptr weak_ptr对比

unique_ptrshared_ptrweak_ptr 就像是内存管理战场上的三员大将,各有千秋,用对了地方才能发挥最大威力。

现代C++中的智能指针有哪些区别 unique_ptr shared_ptr weak_ptr对比

解决方案

首先,unique_ptr,顾名思义,它所指向的对象只能被一个 unique_ptr 拥有。这意味着,所有权是独占的,不能简单地复制。当 unique_ptr 销毁时,它所指向的对象也会被自动删除。这避免了忘记 delete 造成的内存泄漏。

立即学习C++免费学习笔记(深入)”;

#include 
#include 

class MyClass {
public:
    MyClass(int value) : value_(value) {
        std::cout << "MyClass constructed with value: " << value_ << std::endl;
    }
    ~MyClass() {
        std::cout << "MyClass destructed with value: " << value_ << std::endl;
    }

    int getValue() const { return value_; }

private:
    int value_;
};


int main() {
    // 创建一个 unique_ptr,指向一个 MyClass 对象
    std::unique_ptr ptr1 = std::make_unique(10);
    std::cout << "Value: " << ptr1->getValue() << std::endl;

    // 尝试复制 unique_ptr 会导致编译错误
    // std::unique_ptr ptr2 = ptr1; // 错误:unique_ptr 不可复制

    // 可以使用 std::move 转移所有权
    std::unique_ptr ptr2 = std::move(ptr1);
    std::cout << "Value: " << ptr2->getValue() << std::endl;

    // 现在 ptr1 不再拥有对象,访问它会导致未定义行为
    // std::cout << "Value: " << ptr1->getValue() << std::endl; // 避免这样做

    // ptr2 在 main 函数结束时会被销毁,MyClass 对象也会被销毁
    return 0;
}

shared_ptr 则允许多个指针指向同一个对象,它使用引用计数来跟踪有多少个 shared_ptr 指向该对象。只有当引用计数降为零时,对象才会被删除。这使得在多个对象之间共享所有权变得非常方便。但是,循环引用会导致内存泄漏,需要小心。

Cogram
Cogram

使用AI帮你做会议笔记,跟踪行动项目

下载
现代C++中的智能指针有哪些区别 unique_ptr shared_ptr weak_ptr对比
#include 
#include 

class MyClass {
public:
    MyClass(int value) : value_(value) {
        std::cout << "MyClass constructed with value: " << value_ << std::endl;
    }
    ~MyClass() {
        std::cout << "MyClass destructed with value: " << value_ << std::endl;
    }

    int getValue() const { return value_; }

private:
    int value_;
};

int main() {
    // 创建一个 shared_ptr,指向一个 MyClass 对象
    std::shared_ptr ptr1 = std::make_shared(20);
    std::cout << "Value: " << ptr1->getValue() << std::endl;
    std::cout << "Reference count: " << ptr1.use_count() << std::endl;

    // 复制 shared_ptr,引用计数增加
    std::shared_ptr ptr2 = ptr1;
    std::cout << "Value: " << ptr2->getValue() << std::endl;
    std::cout << "Reference count: " << ptr1.use_count() << std::endl;
    std::cout << "Reference count: " << ptr2.use_count() << std::endl;

    // ptr1 和 ptr2 都指向同一个对象,该对象在 main 函数结束时会被销毁一次
    return 0;
}

最后,weak_ptr 是一种“弱引用”,它指向由 shared_ptr 管理的对象,但不增加引用计数。weak_ptr 可以用来观察对象是否仍然存在,而不会阻止对象被删除。这对于解决循环引用问题非常有用。

#include 
#include 

class MyClass {
public:
    MyClass(int value) : value_(value) {
        std::cout << "MyClass constructed with value: " << value_ << std::endl;
    }
    ~MyClass() {
        std::cout << "MyClass destructed with value: " << value_ << std::endl;
    }

    int getValue() const { return value_; }

private:
    int value_;
};

int main() {
    // 创建一个 shared_ptr,指向一个 MyClass 对象
    std::shared_ptr sharedPtr = std::make_shared(30);
    std::cout << "Shared pointer value: " << sharedPtr->getValue() << std::endl;
    std::cout << "Shared pointer reference count: " << sharedPtr.use_count() << std::endl;

    // 创建一个 weak_ptr,指向同一个 MyClass 对象
    std::weak_ptr weakPtr = sharedPtr;
    std::cout << "Weak pointer expired: " << weakPtr.expired() << std::endl;

    // 可以使用 weak_ptr 的 lock() 方法获取一个 shared_ptr
    std::shared_ptr lockedPtr = weakPtr.lock();
    if (lockedPtr) {
        std::cout << "Locked pointer value: " << lockedPtr->getValue() << std::endl;
        std::cout << "Shared pointer reference count: " << sharedPtr.use_count() << std::endl;
    } else {
        std::cout << "Weak pointer is expired." << std::endl;
    }

    // 释放 shared_ptr
    sharedPtr.reset();
    std::cout << "Shared pointer reference count: " << sharedPtr.use_count() << std::endl;
    std::cout << "Weak pointer expired: " << weakPtr.expired() << std::endl;

    // 再次尝试使用 weak_ptr 的 lock() 方法
    lockedPtr = weakPtr.lock();
    if (lockedPtr) {
        std::cout << "Locked pointer value: " << lockedPtr->getValue() << std::endl;
    } else {
        std::cout << "Weak pointer is expired." << std::endl;
    }

    return 0;
}

何时使用 unique_ptr?

当你希望对象的所有权是唯一的,并且在 unique_ptr 销毁时自动删除对象时,使用 unique_ptr。例如,在工厂函数中返回新创建的对象,或者在类中拥有一个独占的资源。

shared_ptr 如何避免循环引用导致的内存泄漏?

循环引用是指两个或多个对象互相持有 shared_ptr,导致引用计数永远不为零,对象永远无法被删除。解决循环引用的方法是使用 weak_ptr。一个对象持有另一个对象的 weak_ptr,而不是 shared_ptr,这样就不会增加引用计数。当需要访问对象时,可以使用 weak_ptr::lock() 方法获取一个 shared_ptr,如果对象已经被删除,lock() 方法会返回 nullptr

weak_ptr 的使用场景有哪些?

除了解决循环引用问题,weak_ptr 还可以用于缓存。例如,一个缓存对象可以使用 weak_ptr 来持有缓存项,当缓存项不再被其他对象使用时,缓存对象会自动释放缓存项。还可以用于观察者模式,观察者可以使用 weak_ptr 来持有被观察者的引用,当被观察者被删除时,观察者可以自动取消订阅。

相关专题

更多
数据库Delete用法
数据库Delete用法

数据库Delete用法:1、删除单条记录;2、删除多条记录;3、删除所有记录;4、删除特定条件的记录。更多关于数据库Delete的内容,大家可以访问下面的文章。

266

2023.11.13

drop和delete的区别
drop和delete的区别

drop和delete的区别:1、功能与用途;2、操作对象;3、可逆性;4、空间释放;5、执行速度与效率;6、与其他命令的交互;7、影响的持久性;8、语法和执行;9、触发器与约束;10、事务处理。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

206

2023.12.29

excel制作动态图表教程
excel制作动态图表教程

本专题整合了excel制作动态图表相关教程,阅读专题下面的文章了解更多详细教程。

24

2025.12.29

freeok看剧入口合集
freeok看剧入口合集

本专题整合了freeok看剧入口网址,阅读下面的文章了解更多网址。

74

2025.12.29

俄罗斯搜索引擎Yandex最新官方入口网址
俄罗斯搜索引擎Yandex最新官方入口网址

Yandex官方入口网址是https://yandex.com;用户可通过网页端直连或移动端浏览器直接访问,无需登录即可使用搜索、图片、新闻、地图等全部基础功能,并支持多语种检索与静态资源精准筛选。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

207

2025.12.29

python中def的用法大全
python中def的用法大全

def关键字用于在Python中定义函数。其基本语法包括函数名、参数列表、文档字符串和返回值。使用def可以定义无参数、单参数、多参数、默认参数和可变参数的函数。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

16

2025.12.29

python改成中文版教程大全
python改成中文版教程大全

Python界面可通过以下方法改为中文版:修改系统语言环境:更改系统语言为“中文(简体)”。使用 IDE 修改:在 PyCharm 等 IDE 中更改语言设置为“中文”。使用 IDLE 修改:在 IDLE 中修改语言为“Chinese”。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

18

2025.12.29

C++的Top K问题怎么解决
C++的Top K问题怎么解决

TopK问题可通过优先队列、partial_sort和nth_element解决:优先队列维护大小为K的堆,适合流式数据;partial_sort对前K个元素排序,适用于需有序结果且K较小的场景;nth_element基于快速选择,平均时间复杂度O(n),效率最高但不保证前K内部有序。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

12

2025.12.29

php8.4实现接口限流的教程
php8.4实现接口限流的教程

PHP8.4本身不内置限流功能,需借助Redis(令牌桶)或Swoole(漏桶)实现;文件锁因I/O瓶颈、无跨机共享、秒级精度等缺陷不适用高并发场景。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

136

2025.12.29

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
C# 教程
C# 教程

共94课时 | 5.6万人学习

C 教程
C 教程

共75课时 | 3.8万人学习

C++教程
C++教程

共115课时 | 10.5万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号