shared_ptr和 weak_ptr的详细介绍

关于 shared_ptrweak_ptr 的详细介绍及使用示例:


1. shared_ptr(共享所有权智能指针)

核心特性
  • 引用计数:记录当前有多少个 shared_ptr 共享同一个对象。
  • 自动释放:当引用计数归零时,自动释放对象内存。
  • 线程安全:引用计数的增减是原子操作(但对象本身的访问需自行同步)。
基本用法
#include <memory>
#include <iostream>class MyClass {
public:MyClass() { std::cout << "MyClass 构造\n"; }~MyClass() { std::cout << "MyClass 析构\n"; }void print() { std::cout << "Hello\n"; }
};int main() {// 创建 shared_ptr(推荐使用 make_shared)std::shared_ptr<MyClass> ptr1 = std::make_shared<MyClass>();// 共享所有权(引用计数+1)std::shared_ptr<MyClass> ptr2 = ptr1;// 使用 -> 操作符访问成员ptr1->print(); // 输出: Hello// 引用计数查看(调试用)std::cout << "引用计数: " << ptr1.use_count() << std::endl; // 输出: 2// ptr1 和 ptr2 离开作用域,引用计数归零,对象自动析构return 0;
}
输出结果
MyClass 构造
Hello
引用计数: 2
MyClass 析构

2. weak_ptr(弱引用智能指针)

核心特性
  • 不增加引用计数:仅观察对象,不影响其生命周期。
  • 需转换为 shared_ptr:通过 lock() 获取临时 shared_ptr 来访问对象。
  • 解决循环引用:打破 shared_ptr 的循环依赖,避免内存泄漏。

3. 循环引用问题与 weak_ptr 解决方案

循环引用示例
#include <memory>
#include <iostream>
class Node {
public:std::shared_ptr<Node> next;Node() { std::cout << "Node 构造\n"; }~Node() { std::cout << "Node 析构\n"; }
};int main() {auto node1 = std::make_shared<Node>();auto node2 = std::make_shared<Node>();node1->next = node2; // node2 引用计数=2node2->next = node1; // node1 引用计数=2// 退出作用域后,node1/node2 引用计数=1,无法释放!return 0;
}
输出结果(内存泄漏)
Node 构造
Node 构造
使用 weak_ptr 解决循环引用
#include <memory>
#include <iostream>
class SafeNode {
public:std::weak_ptr<SafeNode> next; // 使用 weak_ptrSafeNode() { std::cout << "SafeNode 构造\n"; }~SafeNode() { std::cout << "SafeNode 析构\n"; }
};int main() {auto node1 = std::make_shared<SafeNode>();auto node2 = std::make_shared<SafeNode>();node1->next = node2;node2->next = node1;// 退出作用域后,引用计数归零,正确析构return 0;
}
输出结果
SafeNode 构造
SafeNode 构造
SafeNode 析构
SafeNode 析构

4. weak_ptr 的典型使用场景

(1) 访问共享对象前检查存活状态
#include <memory>
#include <iostream>class MyClass {
public:MyClass() { std::cout << "MyClass 构造\n"; }~MyClass() { std::cout << "MyClass 析构\n"; }void print() { std::cout << "Hello\n"; }
};void checkObject(std::weak_ptr<MyClass> weak) {if (auto shared = weak.lock()) { // 转换为 shared_ptrshared->print();} else {std::cout << "对象已被释放\n";}
}int main() {std::weak_ptr<MyClass> weak;{auto shared = std::make_shared<MyClass>();weak = shared;checkObject(weak); // 输出: Hello}checkObject(weak); // 输出: 对象已被释放return 0;
}

输出结果

MyClass 构造
Hello
MyClass 析构
对象已被释放
(2) 观察者模式(缓存)
class DataCache {std::weak_ptr<MyClass> cachedData;
public:void updateCache(std::shared_ptr<MyClass> data) {cachedData = data;}void useCache() {if (auto data = cachedData.lock()) {data->print();} else {std::cout << "缓存无效\n";}}
};

5. shared_ptrweak_ptr 操作总结

操作shared_ptrweak_ptr
所有权拥有对象所有权仅观察对象
引用计数影响增加不影响
访问对象直接通过 ->*需调用 lock() 获取 shared_ptr
检查有效性if (ptr)if (weak.expired())lock()

6. 最佳实践

  1. 优先使用 make_shared:更高效(单次内存分配对象+控制块)。
  2. 避免循环引用:成员指针优先考虑 weak_ptr
  3. 不要用 new 初始化:直接传递裸指针可能导致多次释放。
  4. 谨慎传递 shared_ptr:仅在需要共享所有权时传递,否则传递原始引用或指针。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/74926.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Spring AI MCP 架构详解

Spring AI MCP 架构详解 1.什么是MCP? MCP 是一种开放协议&#xff0c;它对应用程序向大语言模型&#xff08;LLMs&#xff09;提供上下文信息的方式进行了标准化。可以把 MCP 想象成人工智能应用程序的 USB-C 接口。就像 USB-C 为将设备连接到各种外围设备和配件提供了一种…

腾讯系AI应用,可以生视频,3D模型...

以下注册手机后就可以使用了。 腾讯智影 智能抹除-在线去水印去字幕-抹除水印字幕-腾讯智影 混元&#xff08;文字&#xff0c;图片生成3D&#xff09; 腾讯混元3D 混元视频&#xff08;文字生成视频&#xff0c;可惜右下角有文字&#xff09; https://video.hunyuan.tencen…

数据结构(并查集,图)

并查集 练习版 class UnionFindSet { public:void swap(int* a, int* b){int tmp *a;*a *b;*b tmp;}UnionFindSet(size_t size):_ufs(size,-1){}int UnionFind(int x){}void Union(int x1, int x2){}//长分支改为相同节点int FindRoot(int x){}bool InSet(int x1, int x2)…

数据结构:探秘AVL树

本节重点 理解AVL树的概念掌握AVL树正确的插入方法利用_parent指针正确更新平衡因子掌握并理解四种旋转方式&#xff1a;左单旋&#xff0c;右单旋&#xff0c;左右双旋&#xff0c;右左双旋 一、AVL树的概念 AVL树得名于它的发明者G. M. Adelson-Velsky和E. M. Landis&…

电源系统的热设计与热管理--以反激式充电器为例

前言 反激电源常用于各种电子设备中&#xff0c;比如充电器、适配器等&#xff0c;它们通过变压器进行能量转换。高温环境可能对电子元件造成影响&#xff0c;特别是像MOSFET、二极管、变压器这样的关键部件&#xff0c;导致效率变低&#xff0c;甚至可能导致功能失效。还有安…

linux课程学习二——缓存

一.文件io与标准io的一个区别 遇到死循环可以ctrl c结束进程 使用printf输出&#xff0c;输出没有问题 用wirte输出&#xff0c;参数1&#xff0c;可以理解为上面介绍的linux标准文件描述符的1&#xff08;STDOUT&#xff09;标准输出&#xff0c;我们加上一个死循环while&…

Kafka中的消息如何分配给不同的消费者?

大家好&#xff0c;我是锋哥。今天分享关于【Kafka中的消息如何分配给不同的消费者&#xff1f;】面试题。希望对大家有帮助&#xff1b; Kafka中的消息如何分配给不同的消费者&#xff1f; 在 Kafka 中&#xff0c;消息是通过 主题&#xff08;Topic&#xff09; 进行组织的&…

Android的安全问题 - 在 Android 源码的 system/sepolicy 目录中,区分 public、private 和 vendor的目的

参考&#xff1a;Google文档 在 Android 8.0 及更高版本中自定义 SEPolicy 在 Android 源码的 system/sepolicy 目录中&#xff0c;区分 public、private 和 vendor 是为了模块化 SELinux 策略&#xff0c;并明确不同部分的访问权限和接口边界。这种设计主要基于以下原因&…

Java NIO之FileChannel 详解

关键点说明 文件打开选项&#xff1a; StandardOpenOption.CREATE - 文件不存在时创建 StandardOpenOption.READ/WRITE - 读写权限 StandardOpenOption.APPEND - 追加模式 StandardOpenOption.TRUNCATE_EXISTING - 清空已存在文件 缓冲区操作&#xff1a; ByteBuffer.wrap…

stock-pandas,一个易用的talib的替代开源库。

原创内容第841篇&#xff0c;专注智能量化投资、个人成长与财富自由。 介绍一个ta-lib的平替——我们来实现一下&#xff0c;最高价突破布林带上轨&#xff0c;和最低价突破布林带下轨的可视化效果&#xff1a; cross_up_upper stock[high].copy()# cross_up_upper 最高价突破…

JVM 面经

1、什么是 JVM? JVM 就是 Java 虚拟机&#xff0c;它是 Java 实现跨平台的基石。程序运行之前&#xff0c;需要先通过编译器将 Java 源代码文件编译成 Java 字节码文件&#xff1b;程序运行时&#xff0c;JVM 会对字节码文件进行逐行解释&#xff0c;翻译成机器码指令&#x…

【JavaScript】合体期功法——DOM(一)

目录 DOMWeb API 基本概念作用和分类 什么是 DOMDOM 树DOM 对象 获取 DOM 元素根据 CSS 选择器来获取 DOM 元素选择匹配的第一个元素选择匹配的多个元素 其他获取 DOM 元素方法 修改元素的内容对象.innerText 属性对象.innerHTML 属性案例&#xff1a;年会抽奖 修改元素属性修改…

GAMMA数据处理(十)

今天向别人请教了一个问题&#xff0c;刚无意中搜索到了一模一样的问题 不知道这个怎么解决... ok 解决了 有一个GAMMA的命令可转换 但是很奇怪 完全对不上 转换出来的行列号 不知道为啥 再试试 是因为经纬度坐标的小数点位数 de as

Java入门知识总结——章节(二)

ps&#xff1a;本章主要讲数组、二维数组、变量 一、数组 数组是一个数据容器&#xff0c;可用来存储一批同类型的数据 &#x1f511;&#xff1a;注意 类也可以是一个类的数组 public class Main {public static class Student {String name;int age; // 移除 unsignedint…

动态IP:网络世界的“变色龙”如何改变你的在线体验?

你知道吗&#xff1f;有时候我觉得动态IP就像是网络世界里的“变色龙”。它不像静态IP那样一成不变&#xff0c;而是随时在变化&#xff0c;像是一个永远在换衣服的演员。你永远不知道它下一秒会变成什么样子&#xff0c;但正是这种不确定性&#xff0c;让它变得特别有趣。想象…

从24GHz到71GHz:Sivers半导体的广泛频率范围5G毫米波产品解析

在5G技术的浪潮中&#xff0c;Sivers半导体推出了创新的毫米波无线产品&#xff0c;为通信行业带来高效、可靠的解决方案。这些产品支持从24GHz到71GHz的频率&#xff0c;覆盖许可与非许可频段&#xff0c;适应高速、低延迟的通信场景。 5G通信频段的一点事儿及Sivers毫米波射频…

aocache:AOCache 新增功能深度解析:从性能监控到灵活配置的全方位升级

最近对aocache 进行了重要升级&#xff0c;最新版本0.6.0增加了几项新功能&#xff1a;性能分析日志&#xff0c;AOCache性能分析工具&#xff0c;切入点自定义配置&#xff0c;全局配置&#xff0c;本文详细说明这几项目新功能的作用和使用方式。 一、性能分析日志 需求背景…

Java EE 进阶:MyBatis-plus

MyBatis-plus的介绍 MyBatis-plus是MyBatis的增强工具&#xff0c;在MyBatis的基础上做出加强&#xff0c;只要MyBatis有的功能MyBatis-plus都有。 MyBatis-plus的上手 添加依赖 在我们创建项目的时候&#xff0c;我们需要添加MyBatis-plus和mysql的依赖 MyBatis-plus的依赖…

GitHub和Gitee上的一些AI项目

以下是GitHub和Gitee上的一些AI项目&#xff1a; GitHub上的AI项目 TensorFlow&#xff1a;一个端到端开源机器学习平台&#xff0c;包含大量工具和库&#xff0c;广泛应用于图像识别、自然语言处理等领域。PyTorch&#xff1a;由Facebook开发的开源深度学习框架&#xff0c;…

JavaScript网页设计高级案例:构建交互式图片画廊

JavaScript网页设计高级案例&#xff1a;构建交互式图片画廊 在现代Web开发中&#xff0c;交互式元素已成为提升用户体验的关键因素。本文将通过一个高级案例 - 构建交互式图片画廊&#xff0c;展示如何结合HTML和JavaScript创建引人入胜的网页应用。这个案例不仅涵盖了基础的…