当前位置: 首页 > article >正文

智能指针相关

零、预备知识右值表示不可寻址的临时数据值。根据C11标准右值分为纯右值如字面量、表达式结果和将亡值即将销毁的对象。 右值具有不可修改、无持久内存地址的特性右值引用、移动语义、完美转发https://learn.microsoft.com/zh-cn/cpp/cpp/rvalue-reference-declarator-amp-amp?viewmsvc-170一、unique_ptr#includeiostream using namespace std; templatetypename T class MyUniquePtr { private: T* ptr_; public: MyUniquePtr(T *pnullptr):ptr_(p){} ~MyUniquePtr() { delete ptr_; ptr_ nullptr; } MyUniquePtr(const MyUniquePtr) delete; MyUniquePtr operator(const MyUniquePtr) delete; MyUniquePtr(MyUniquePtr other) noexcept : ptr_(other.ptr_) { other.ptr_ nullptr; } MyUniquePtr operator(MyUniquePtr other) noexcept { if(this ! other) // { delete ptr_; // ptr_ other.ptr_; // other.ptr_ nullptr; // } return *this; } T operator*() { return *ptr_; } T* operator-() { return ptr_; } // T* get() const { return ptr_; } // }; void MyUniquePtr_demo() { MyUniquePtrint p1(new int(42)); MyUniquePtrint p2(new int(10)); coutp1: p1endl; coutp2: p2endl; MyUniquePtrint p3 std::move(p2); coutp1: p1endl; coutp2: p2endl; coutp3: p3endl; MyUniquePtrintp4(std::move(p3)); coutp1: p1endl; coutp2: p2endl; coutp3: p3endl; coutp4: p4endl; p2 std::move(p1); coutp1: p1endl; coutp2: p2endl; }二、shared_ptr#includeiostream using namespace std; templatetypename T class MySharedPtr { private: T* ptr_; int* ref_count; void Relese() { if(ref_count !nullptr) { --*ref_count; if(*ref_count 0) { delete ptr_; delete ref_count; } ptr_ nullptr; ref_count nullptr; } } public: MySharedPtr(T* p nullptr) : ptr_(p),ref_count(nullptr) { if(ptr_ ! nullptr) ref_count new int(1); } ~MySharedPtr() { Relese(); } MySharedPtr(const MySharedPtr other) { ptr_ other.ptr_; ref_count other.ref_count; if(ref_count ! nullptr) *ref_count; } MySharedPtr operator(const MySharedPtr other) { if(this ! other) { Relese(); ptr_ other.ptr_; ref_count other.ref_count; if(ref_count ! nullptr) *ref_count; } return *this; } T operator*() { return *ptr_; } T* operator-() { return ptr_; } T* get() const { return ptr_; } int use_count() const { return ref_count ! nullptr ? *ref_count : 0; } }; void test_shared_ptr() { // 1. 测试构造 MySharedPtrint p1(new int(100)); cout p1 count: p1.use_count() endl; // 预期: 1 // 2. 测试拷贝构造 MySharedPtrint p2 p1; cout p1 count: p1.use_count() endl; // 预期: 2 cout p2 count: p2.use_count() endl; // 预期: 2 // 3. 测试独立指针 MySharedPtrint p3(new int(200)); cout p3 count: p3.use_count() endl; // 预期: 1 // 4. 测试赋值运算符 (p3 放弃 200接管 100) p3 p1; // 此时原本的 200 应该被自动 delete cout p1 count: p1.use_count() endl; // 预期: 3 cout p3 count: p3.use_count() endl; // 预期: 3 }三、weak_ptr#includeiostream using namespace std; struct ControlBlock { int shared_count; int weak_count; }; templatetypename T class MyWeakPtr; templatetypename T class SharedPtr { private: ControlBlock *cb; T* ptr_; void Release() { if(cb ! nullptr) { --cb-shared_count; if(cb-shared_count 0) { delete ptr_; if(cb-weak_count 0) { delete cb; } } cb nullptr; ptr_ nullptr; } } public: SharedPtr(T* pnullptr) : ptr_(p) , cb(nullptr) { if(ptr_ ! nullptr) { cb new ControlBlock; cb-shared_count 1; cb-weak_count 0; } } ~SharedPtr() { Release(); } SharedPtr(const SharedPtr other) { ptr_ other.ptr_; cb other.cb; if(cb ! nullptr) cb-shared_count; } SharedPtr(const MyWeakPtrT wp) : ptr_(nullptr),cb(nullptr) { if(!wp.expired()) { ptr_ wp.ptr_; cb wp.cb; cb-shared_count; } } SharedPtr operator(const SharedPtr other) { if(this ! other) { Release(); ptr_ other.ptr_; cb other.cb; if(ptr_ ! nullptr) cb-shared_count; } return *this; } T operator*(){return *ptr_;} T* operator-(){return ptr_;} T* get() const { return ptr_; } int use_count() const { return cb ! nullptr ? cb-shared_count : 0; } friend class MyWeakPtrT; }; templatetypename T class MyWeakPtr { private: T* ptr_; ControlBlock *cb; void Release() { if(cb ! nullptr) { --cb-weak_count; if(cb-shared_count 0 cb-weak_count 0) { delete cb; } cb nullptr; } } public: T* operator-() delete; T operator*() delete; MyWeakPtr() : ptr_(nullptr), cb(nullptr) {} // 默认无参构造 MyWeakPtr(const SharedPtrT p) : ptr_(p.ptr_),cb(p.cb) { if(cb ! nullptr) cb-weak_count; } ~MyWeakPtr() { Release(); } MyWeakPtr(const MyWeakPtrT other) { ptr_ other.ptr_; cb other.cb; if(ptr_ ! nullptr) cb-weak_count; } MyWeakPtr operator(const MyWeakPtrT other) { if(this ! other) { Release(); ptr_ other.ptr_; cb other.cb; if(cb ! nullptr) cb-weak_count; } return *this; } MyWeakPtr operator(const SharedPtrT other) { Release(); ptr_ other.ptr_; cb other.cb; if(cb ! nullptr) cb-weak_count; return *this; } bool expired() const {return cb nullptr || cb-shared_count 0 ;} friend class SharedPtrT; SharedPtrT lock() const { if(expired()) return SharedPtrT(nullptr); return SharedPtrT(*this); } }; // --- 准备测试类 --- class Girl; // 前向声明 class Boy { public: string name; SharedPtrGirl girl_friend; // 强引用 Boy(string n) : name(n) { cout [Constructor] Boy name created.\n; } ~Boy() { cout [Destructor] Boy name destroyed.\n; } void setGirl(SharedPtrGirl g) { girl_friend g; } }; class Girl { public: string name; // --- 关键点这里如果用 SharedPtr 就会导致循环引用 --- MyWeakPtrBoy boy_friend; Girl(string n) : name(n) { cout [Constructor] Girl name created.\n; } ~Girl() { cout [Destructor] Girl name destroyed.\n; } void setBoy(SharedPtrBoy b) { boy_friend b; } }; // --- 测试函数 1基础功能与 lock --- void test_basic_and_lock() { cout \n--- Starting Basic and Lock Test ---\n; MyWeakPtrint wp; { SharedPtrint sp(new int(42)); wp sp; cout Shared count (sp): sp.use_count() endl; // 预期: 1 // 测试 lock() 成功 SharedPtrint sp_locked wp.lock(); if (sp_locked.get() ! nullptr) { cout Lock successful, value: *sp_locked endl; // 预期: 42 cout Shared count after lock: sp_locked.use_count() endl; // 预期: 2 } } // sp 离开作用域计数减为 0内存释放 // 测试 expired() 和 lock() 失败 if (wp.expired()) { cout Object has been destroyed (expired).\n; // 预期执行 } SharedPtrint sp_failed wp.lock(); if (sp_failed.get() nullptr) { cout Lock failed after object destruction.\n; // 预期执行 } cout --- Basic Test Finished ---\n; } // --- 测试函数 2循环引用打破测试 --- void test_circular_reference() { cout \n--- Starting Circular Reference Test ---\n; { SharedPtrBoy tom(new Boy(Tom)); SharedPtrGirl rose(new Girl(Rose)); tom-setGirl(rose); // Tom 强引用 Rose rose-setBoy(tom); // Rose 弱引用 Tom cout Tom shared_count: tom.use_count() endl; // 预期: 1 (Rose是弱引用) cout Rose shared_count: rose.use_count() endl; // 预期: 1 (Tom是强引用) cout Leaving inner scope...\n; } // 预期结果在这里应该看到 Tom 和 Rose 的 Destructor 被调用。 // 如果没有看到打印销毁信息说明你的 weak_ptr 没有成功打破循环引用。 cout --- Circular Reference Test Finished ---\n; }

相关文章:

智能指针相关

零、预备知识 右值: 表示不可寻址的临时数据值。 根据C11标准,右值分为纯右值(如字面量、表达式结果)和将亡值(即将销毁的对象)。 右值具有不可修改、无持久内存地址的特性 右值引用&&、移动语义…...

当立体车库遇上PLC仿真

西门子1200PLC立体车库 33立体车库 博图触摸屏仿真 不需要实物 自带人机界面,动画,可以仿真 还有接线图原理图 现在拥有自动出入仓库的功能 IO表已列出最近捣鼓了个挺有意思的项目——基于西门子1200PLC的33立体车库仿真。不用焊线接电机,纯…...

HTML基础教程(一)

目录 一、HTML基本概念 二、基础HTML (Tag) 三、Html常用格式 一、HTML基本概念 什么是HTML文件? HTML的英文全称是Hypertext Marked Language,中文叫做“超文本标记语言”。和一般文本的不同的是,一个HTML文件不…...

AI基石 | 对齐技术:从 RLHF 到 DPO —— 赋予大模型“三观”的终极进化

AI基石 | 对齐技术:从 RLHF 到 DPO —— 赋予大模型“三观”的终极进化 前言 如果 SFT(监督微调)后的模型是一个“懂事”的练习生,那么对齐后的模型就是一个“老练”的专家。 练习生虽然知道问答的格式,但依然存在两个…...

俄罗斯RT-2PM2“白杨-M“(Topol-M)洲际弹道导弹系统完整技术报告

Comprehensive Technical Report on Russias RT-2PM2 Topol-M Intercontinental Ballistic Missile System 报告日期:2026年3月11日 保密级别:公开来源情报(OSINT) 摘要(Executive Summary) RT-2PM2"…...

Java线程池面试题50道(含答案解析)

在Java后端开发面试中,线程池(ThreadPool) 是并发编程的重要考点之一。 在高并发系统中,合理使用线程池可以 提高系统性能、减少线程创建开销、避免资源耗尽。 很多互联网公司在面试Java工程师时都会重点考察: 线程池原…...

Clawdbot 杀红眼了,几天怒斩 80k+ Star!你真正的 AI 数字员工来了!!(附保姆级安装使用教程)

最近一款 AI 开源工具 Clawdbot 杀疯了,人送外号:大龙虾,短短几天时间,GitHub 上 Star 数量暴涨到 80k,因为名称与 Claude 相似,还被 Anthropic 公司警告被迫改名:Moltbot。 Moltbot 的核心是它…...

Python3.9环境配置太麻烦?试试这个Miniconda镜像,一键部署

Python3.9环境配置太麻烦?试试这个Miniconda镜像,一键部署 还在为配置Python开发环境而头疼吗?从源码编译安装,要解决一堆依赖问题;手动下载安装包,又担心版本冲突和路径混乱。特别是当你需要Python 3.9这…...

从原理到代码:深度解析Halcon中segment_contours_xld的Ramer算法实现

从原理到代码:深度解析Halcon中segment_contours_xld的Ramer算法实现 在机器视觉的工程实践中,我们常常需要将相机捕捉到的、由像素点构成的连续轮廓,转化为更高级、更易于理解和处理的几何基元,比如直线、圆弧或椭圆弧。这个过程…...

Keil5 vs Keil6:如何选择?附带Keil5中STM32开发环境搭建全攻略(含FreeRTOS移植准备)

Keil MDK 进化论:从经典到现代,如何为你的STM32项目选择最佳开发环境 作为一名在嵌入式领域摸爬滚打了多年的开发者,我至今还记得第一次打开Keil MDK时那种既兴奋又茫然的心情。那个经典的蓝色界面,几乎成了ARM Cortex-M开发的代名…...

第三期:基于立创·梁山派开发板的游戏机扩展板训练营全记录

第三期:基于立创梁山派开发板的游戏机扩展板训练营全记录 大家好,我是老张,一个在嵌入式行业摸爬滚打了十几年的工程师。最近,我作为导师完整地跟进了立创EDA举办的“梁山派游戏机扩展板训练营”第三期。看到很多朋友对如何从零开…...

OAuth2.0中state参数的深度应用:业务数据的安全传输与防CSRF实践

1. 不只是防CSRF:重新认识OAuth2.0的state参数 很多刚开始接触OAuth2.0的开发者,一看到state参数,第一反应就是“哦,防CSRF的”。这个理解没错,但只对了一半。在实际项目中,尤其是在需要深度集成的场景里&a…...

Ubuntu20.04下拯救者笔记本亮度调节失效?NVIDIA驱动加载顺序问题全解析

Ubuntu 20.04 下拯救者笔记本亮度调节失效?NVIDIA 驱动加载顺序问题全解析 最近在联想拯救者系列笔记本上安装 Ubuntu 20.04 的朋友,可能都遇到过同一个令人头疼的问题:屏幕亮度过高,刺眼得让人无法工作,而无论是系统设…...

SAR动目标检测系列:【5】多基线联合处理下的三维速度解耦

1. 从二维到三维:为什么我们需要多基线联合处理? 在上一篇文章里,我们聊透了如何利用单天线或者双天线SAR系统,去估计动目标的二维速度(也就是方位向和距离向的速度)。这就像你用手机拍一个移动的物体&…...

Flink实战:如何用KeyedProcessFunction实现温度异常检测(附完整代码)

从零构建实时温度异常检测系统:深入Flink KeyedProcessFunction核心实战 最近在帮一个做智慧农业的朋友处理温室大棚的监控数据,他们部署了上百个温湿度传感器,数据像潮水一样涌来。最头疼的不是数据量大,而是如何从这些实时流里快…...

KITTI 3D 数据可视化:从点云到鸟瞰图的实战解析

1. 从零开始:理解KITTI数据集与3D点云 大家好,我是老张,在自动驾驶这个行当里摸爬滚打了十来年,跟激光雷达和相机数据打了无数次交道。今天,我想跟你聊聊一个非常基础但又极其重要的技能:如何把KITTI数据集…...

内存马二:Filter

Filter内存马 源码学习 首先写一个普通的Filter了解一下重点数据的传递过程,断点到内部的一行,往上找。回到的是org.apache.catalina.core.ApplicationFilterChain#internalDoFilter,这部分找到filters找filters的赋值的地方,找到…...

uni-id-pages配置email

uniappuniclouduni-id-pages 配置邮箱教程 安装uni-id-pages插件下载插件并导入HbuilderX 修改/uni_modules/uni-id-pages/uniCloud/cloudfunctions/uni-id-co/module/verify/send-email-code.js文件内容,将测试代码注释,添加发送邮件代码 // -- 测试代码// awai…...

Android 休眠机制详解 ——WakeLock、Doze 模式与待机功耗优化实战

前言 待机功耗高、耗电快、手表 / 手机一觉醒来掉电很多,90% 都是 “休眠没睡进去”。 一、为什么要讲 Android 休眠? 对手机 / 手表 / IoT 设备来说: 亮屏 性能息屏待机 续航 功耗测试的核心,就是看设备能不能正常休眠、睡不睡…...

C++中的装饰器模式高级应用

1、非修改序列算法这些算法不会改变它们所操作的容器中的元素。1.1 find 和 find_iffind(begin, end, value):查找第一个等于 value 的元素,返回迭代器(未找到返回 end)。find_if(begin, end, predicate):查找第一个满…...

LeetCode 3296.移山所需的最少秒数:优先队列

【LetMeFly】3296.移山所需的最少秒数:优先队列 力扣题目链接:https://leetcode.cn/problems/minimum-number-of-seconds-to-make-mountain-height-zero/ 给你一个整数 mountainHeight 表示山的高度。 同时给你一个整数数组 workerTimes,表…...

深入解析尺度空间理论及其在SIFT特征提取中的应用

1. 从“看画”说起:为什么我们需要尺度空间? 想象一下,你站在一幅巨大的油画前,比如梵高的《星空》。当你把鼻子都快贴到画布上时,你只能看到一小片区域,那里有清晰的、厚重的笔触和颜料的纹理。你后退一步…...

Spring Boot文件上传报错Failed to parse multipart servlet request的3种解决方案及适用场景

1. 问题重现:那个让人头疼的“Failed to parse multipart servlet request” 不知道你有没有遇到过这种情况:一个好好的Spring Boot文件上传功能,平时用着都挺顺溜,突然有一天,用户反馈说上传文件报错了。你赶紧去查日…...

0.96寸OLED取模实战:从基础字符到动态图像显示

1. 为什么你的OLED屏幕只能显示英文?聊聊取模这回事 你是不是也遇到过这种情况?兴冲冲地买回来一块小巧精致的0.96寸OLED屏幕,连上Arduino或者ESP32,跑了个示例程序,屏幕上“Hello World”亮起,感觉科技感满…...

【C++】MSYS2进阶:从零到一打造现代化C++工作流

1. 为什么你的C开发环境需要一个“瑞士军刀”? 如果你在Windows上折腾过C开发环境,大概率经历过一场噩梦:去MinGW官网下载编译器,手动配置环境变量,再单独安装CMake、Ninja、GDB……每个工具都有自己的安装包和路径&am…...

ESP32-C61 TIMG定时器与看门狗深度实践指南

ESP32-C61 定时器组(TIMG)与看门狗定时器深度实践指南1. TIMG 架构概览与中断机制解析ESP32-C61 的定时器组(TIMG)是系统级时间管理的核心硬件模块,集成于两个独立的定时器组(TIMG0 和 TIMG1)&a…...

提示工程架构师揭秘:AI提示系统个性化与用户画像结合的4大方法

提示工程架构师揭秘:AI提示系统个性化与用户画像结合的4大方法 摘要/引言 在当今AI技术飞速发展的时代,AI提示系统已广泛应用于各种场景。然而,通用的提示往往无法满足每个用户的特定需求。本文旨在解决如何通过将AI提示系统与用户画像相结合…...

立创Ai8051U测控开发板:从传感器采集到无线通信的综合嵌入式实战平台

立创Ai8051U测控开发板:从传感器采集到无线通信的综合嵌入式实战平台 最近有不少朋友问我,想找一个能“一站式”学习嵌入式系统所有核心环节的开发板,从最基础的GPIO控制,到传感器数据采集、存储、显示,再到无线通信和…...

立创开源复古辉光管时钟DIY全解析:ESP32-C3驱动IN-12A与170V升压电路设计

立创开源复古辉光管时钟DIY全解析:ESP32-C3驱动IN-12A与170V升压电路设计 最近在捣鼓一个特别有感觉的复古小玩意儿——辉光管时钟。看着那橘红色的数字在玻璃管里幽幽亮起,瞬间有种穿越回上世纪的感觉。很多朋友看了我做的成品都心痒痒,但一…...

提示工程架构师必学:Agentic AI中的强化学习结合策略

提示工程架构师必学:Agentic AI中的强化学习结合策略 引言 背景介绍 在当今人工智能的快速发展浪潮中,Agentic AI(智能体人工智能)正逐渐成为研究和应用的热点。Agentic AI旨在构建能够自主感知环境、做出决策并采取行动以实现特定…...