0

0

C++weak_ptr访问被释放对象处理技巧

P粉602998670

P粉602998670

发布时间:2025-09-09 09:51:01

|

632人浏览过

|

来源于php中文网

原创

weak_ptr通过lock()获取shared_ptr来安全访问对象,避免悬空指针;常用于解决循环引用、实现观察者模式、缓存及对象存活检测,选择时根据是否需控制生命周期决定。

c++weak_ptr访问被释放对象处理技巧

C++

weak_ptr
的主要作用是在不增加对象引用计数的前提下持有对象的引用,解决循环引用的问题。当
weak_ptr
尝试访问的对象已经被释放时,它会变成 expired,因此需要在使用前进行检查,避免访问悬空指针。

解决方案

使用

weak_ptr
时,先通过
lock()
方法尝试获取
shared_ptr
。如果对象仍然存在,
lock()
会返回一个有效的
shared_ptr
;如果对象已经被释放,
lock()
会返回一个空的
shared_ptr

#include 
#include 

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

    void printData() {
        std::cout << "Data: " << data << std::endl;
    }
};

int main() {
    std::weak_ptr weakPtr;

    {
        std::shared_ptr sharedPtr = std::make_shared(42);
        weakPtr = sharedPtr;

        // 使用 weak_ptr 访问对象
        std::shared_ptr lockedPtr = weakPtr.lock();
        if (lockedPtr) {
            lockedPtr->printData(); // 安全访问
        } else {
            std::cout << "Object has been destroyed." << std::endl;
        }
    } // sharedPtr 超出作用域,对象被释放

    // 再次尝试访问
    std::shared_ptr lockedPtr = weakPtr.lock();
    if (lockedPtr) {
        lockedPtr->printData();
    } else {
        std::cout << "Object has been destroyed." << std::endl; // 输出此行
    }

    return 0;
}

如何避免
weak_ptr
访问悬空指针导致的崩溃?

  1. 始终在使用前检查

    weak_ptr
    是否有效: 使用
    weak_ptr.lock()
    获取
    shared_ptr
    ,并检查返回的
    shared_ptr
    是否为空。这是最核心的原则。

  2. 注意对象生命周期: 了解对象何时可能被释放,避免在对象已经被释放后尝试访问。 虽然无法完全预测,但良好的设计可以减少意外情况。

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

  3. 避免在多线程环境下出现竞争: 如果

    weak_ptr
    在多线程环境下使用,确保在访问前进行适当的同步,防止在检查后、访问前对象被释放。例如,使用互斥锁保护对
    weak_ptr
    的访问。

weak_ptr
还能用于哪些场景?

除了解决循环引用,

weak_ptr
还有其他一些应用场景:

  1. 观察者模式: 观察者持有对主题的

    weak_ptr
    ,当主题被销毁时,观察者可以安全地停止观察,避免访问无效对象。

    LongShot
    LongShot

    LongShot 是一款 AI 写作助手,可帮助您生成针对搜索引擎优化的内容博客。

    下载
  2. 缓存: 缓存可以持有对对象的

    weak_ptr
    ,如果对象被其他地方释放,缓存可以自动清理过期条目。

  3. 检测对象是否存活: 可以通过将

    shared_ptr
    转换为
    weak_ptr
    ,然后在稍后检查
    weak_ptr.expired()
    来判断对象是否仍然存活。

如何选择使用
weak_ptr
还是
shared_ptr

选择

weak_ptr
还是
shared_ptr
取决于所有权关系:

  • shared_ptr
    表示共享所有权。多个
    shared_ptr
    可以指向同一个对象,只有当所有
    shared_ptr
    都被销毁时,对象才会被释放。

  • weak_ptr
    表示非拥有关系。
    weak_ptr
    可以观察对象,但不会阻止对象被释放。它只是提供了一种在对象仍然存在时访问它的方式。

如果需要控制对象的生命周期,应该使用

shared_ptr
。如果只是需要观察对象,而不希望影响其生命周期,应该使用
weak_ptr
。通常,循环引用需要使用
weak_ptr
来打破。

相关专题

更多
线程和进程的区别
线程和进程的区别

线程和进程的区别:线程是进程的一部分,用于实现并发和并行操作,而线程共享进程的资源,通信更方便快捷,切换开销较小。本专题为大家提供线程和进程区别相关的各种文章、以及下载和课程。

472

2023.08.10

Python 多线程与异步编程实战
Python 多线程与异步编程实战

本专题系统讲解 Python 多线程与异步编程的核心概念与实战技巧,包括 threading 模块基础、线程同步机制、GIL 原理、asyncio 异步任务管理、协程与事件循环、任务调度与异常处理。通过实战示例,帮助学习者掌握 如何构建高性能、多任务并发的 Python 应用。

108

2025.12.24

空指针异常处理
空指针异常处理

本专题整合了空指针异常解决方法,阅读专题下面的文章了解更多详细内容。

20

2025.11.16

php源码安装教程大全
php源码安装教程大全

本专题整合了php源码安装教程,阅读专题下面的文章了解更多详细内容。

65

2025.12.31

php网站源码教程大全
php网站源码教程大全

本专题整合了php网站源码相关教程,阅读专题下面的文章了解更多详细内容。

45

2025.12.31

视频文件格式
视频文件格式

本专题整合了视频文件格式相关内容,阅读专题下面的文章了解更多详细内容。

40

2025.12.31

不受国内限制的浏览器大全
不受国内限制的浏览器大全

想找真正自由、无限制的上网体验?本合集精选2025年最开放、隐私强、访问无阻的浏览器App,涵盖Tor、Brave、Via、X浏览器、Mullvad等高自由度工具。支持自定义搜索引擎、广告拦截、隐身模式及全球网站无障碍访问,部分更具备防追踪、去谷歌化、双内核切换等高级功能。无论日常浏览、隐私保护还是突破地域限制,总有一款适合你!

41

2025.12.31

出现404解决方法大全
出现404解决方法大全

本专题整合了404错误解决方法大全,阅读专题下面的文章了解更多详细内容。

232

2025.12.31

html5怎么播放视频
html5怎么播放视频

想让网页流畅播放视频?本合集详解HTML5视频播放核心方法!涵盖<video>标签基础用法、多格式兼容(MP4/WebM/OGV)、自定义播放控件、响应式适配及常见浏览器兼容问题解决方案。无需插件,纯前端实现高清视频嵌入,助你快速打造现代化网页视频体验。

9

2025.12.31

热门下载

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

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Python全栈开发教程-入门到精通
Python全栈开发教程-入门到精通

共106课时 | 6.5万人学习

黑马云课堂mongodb实操视频教程
黑马云课堂mongodb实操视频教程

共11课时 | 3.1万人学习

vscode其实很简单
vscode其实很简单

共72课时 | 28.8万人学习

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

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