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

Rust- 智能指针

Smart pointers

A smart pointer is a data structure that not only acts like a pointer but provides additional functionality. This “smartness” comes from the fact that smart pointers encapsulate additional logical or semantic rules, which are automatically applied to simplify memory or resource management tasks.

While different programming languages implement smart pointers in various ways, they all share a common goal: to manage the life cycle of the resources they point to.

Here are some key features of smart pointers:

  1. Ownership: Smart pointers keep track of the memory they point to, and can automatically reclaim (or “free”) that memory when it’s no longer needed. This can greatly simplify memory management, as the programmer doesn’t need to manually release memory, reducing the risk of memory leaks.

  2. Reference Counting: Some smart pointers, like the Rc<T> in Rust or shared_ptr in C++, keep a count of the number of references (i.e., pointers) to an object. This object is only deallocated when there are no more references to it.

  3. Dereferencing: Like regular pointers, smart pointers implement the dereferencing operation, allowing access to the data they point to.

  4. Polymorphism: In object-oriented languages, smart pointers can be used to enable polymorphism when pointing to base and derived class objects.

  5. Thread Safety: Some smart pointers, like Arc<T> in Rust or std::atomic_shared_ptr in C++20, are thread-safe, meaning they can be safely used in concurrent programming.

In Rust, smart pointers are essential components due to the language’s focus on safety and zero-cost abstractions. Box<T>, Rc<T>, and RefCell<T> are some of the commonly used smart pointers in Rust.

  1. Box<T>: This is the simplest kind of smart pointer. It allows you to put data on the heap rather than the stack. Box<T> is often used in Rust in two scenarios: when you have a type of known size but need to store a value of a type that might have an unknown size at compile time, or when you have a large data item and want to transfer ownership to a function without copying the data to prevent stack overflow.

  2. Rc<T>: “Rc” stands for reference counting. The Rc<T> smart pointer allows your program to have multiple read-only references to the same data item on the heap. It keeps track of the number of references to the data on the heap, and once the reference count goes to zero, meaning there are no more references to the data, it cleans up the data.

  3. RefCell<T>: Rust performs borrow checking at compile time which ensures that references to data obey the rules of either one write or multiple reads. However, sometimes you may need to do such checking at runtime. RefCell<T> provides this functionality. This means that while you can borrow mutable references at runtime, your program will panic if you violate the rules of one write or multiple reads.

These are some of the basic smart pointers in Rust. There are several other smart pointers, like Arc<T>, Mutex<T>, etc., which are all designed to deal with ownership and concurrency issues in Rust.

It’s worth noting that while these types are called “smart pointers”, they’re not limited to mimicking pointer-like behavior. They’re actually more general constructs often used to add structure to a value, such as tracking reference counts, thread-safe access, and more.

Box< T >

Box<T> is a very important smart pointer in Rust. It allows you to store data on the heap rather than the stack. This is mainly used in Rust for the following two scenarios:

  1. Moving data to the heap: By default, Rust stores data on the stack. However, stack space is limited and the data on the stack is immediately removed when it goes out of scope. If you need to store a large amount of data in memory or need to pass data between scopes without losing ownership, you can use Box<T> to move the data to the heap.

  2. Storing dynamically sized types: In Rust, the size of all types must be known at compile time. However, there might be cases where you want to store a type whose size is not known at compile time. Box<T> can be used in this case, as the size of Box<T> itself is known regardless of the size of the data on the heap it points to.

When using Box<T>, Rust will automatically clean up the data on the heap when the Box<T> goes out of scope, meaning you do not need to manually manage memory.

Here is a simple example of Box<T>:

fn main() {let b = Box::new(5); // b is a pointer to a box in the heapprintln!("b = {}", b);
}

In this example, the integer 5 is stored on the heap, rather than on the stack. The variable b is a pointer to the value stored on the heap. When b goes out of scope, Rust’s automatic memory management system cleans up the data on the heap, so you do not need to manually free the memory.

use std::ops::Deref;
fn main() {/*如果一个结构体实现了deref和drop的Trait,那他们就不是普通结构体了。Rust提供了堆上存储数据的能力并把这个能力封装到了Box中。把栈上的数据搬到堆上的能力,就叫做装箱。Box可以把数据存储到堆上,而不是栈上,box 装箱,栈还是包含指向堆上数据的指针。*/let a = 6;let b = Box::new(a);println!("b = {}", b); // b = 6let price1 = 158;let price2 = Box::new(price1);println!("{}", 158 == price1);  // trueprintln!("{}", 158 == *price2); // truelet x = 666;let y = CustomBox::new(x);println!("666 == x is {}", 666 == x);   // 666 == x is trueprintln!("666 == *y is {}", 666 == *y); // 666 == *y is trueprintln!("x == *y is {}", x == *y);     // x == *y is true
}struct CustomBox<T> {value: T
}impl <T> CustomBox<T> {fn new(v: T) -> CustomBox<T> {CustomBox { value: v }}
}impl <T> Deref for CustomBox<T> {type Target = T;fn deref(&self) -> &T {&self.value}
}impl <T> Drop for CustomBox<T> {fn drop(&mut self) {println!("drop CustomBox 对象!")}
}

Rc < T >

Rc<T> stands for ‘Reference Counting’. It’s a smart pointer that allows you to have multiple owners of the same data. When each owner goes out of scope, the reference count is decreased. When the count reaches zero, the data is cleaned up.

Here’s a simple example:

use std::rc::Rc;fn main() {let data = Rc::new("Hello, World!"); // data now has a reference count of 1{let _clone = Rc::clone(&data); // data now has a reference count of 2println!("Inside the scope, data is: {}", *_clone);} // _clone goes out of scope and data's reference count decreases to 1println!("Outside the scope, data is: {}", *data);
} // data goes out of scope and its reference count decreases to 0, the data is cleaned up

RefCell < T >

RefCell<T> provides ‘interior mutability’, a design pattern in Rust that allows you to mutate data even when there are immutable references to that data. It enforces the borrowing rules at runtime instead of compile time.

Here’s a simple example:

use std::cell::RefCell;fn main() {let data = RefCell::new(5);{let mut mutable_reference = data.borrow_mut();*mutable_reference += 1;println!("Inside the scope, data is: {}", *mutable_reference);} // mutable_reference goes out of scope, the lock is releasedprintln!("Outside the scope, data is: {}", *data.borrow());
}

In this example, you can see that we borrowed a mutable reference to the data inside RefCell using borrow_mut, modified it, and then the lock was automatically released when the mutable reference went out of scope. This demonstrates the dynamic checking that RefCell<T> provides.

Note1: The borrow_mut() function is a method of RefCell<T> in Rust. This function is used to gain mutable access to the underlying value that the RefCell wraps around.

The RefCell struct in Rust enforces the borrow rules at runtime, allowing you to have multiple immutable references or one mutable reference at any point in time. If you attempt to violate these rules, your program will panic at runtime.

When you call borrow_mut() on a RefCell, you get a RefMut smart pointer that allows mutable access to the underlying data. Once this RefMut is dropped (which happens automatically when it goes out of scope), others can then borrow the RefCell again.

Here’s an example:

use std::cell::RefCell;fn main() {let data = RefCell::new(5);{let mut mutable_reference = data.borrow_mut();*mutable_reference += 1;println!("Inside the scope, data is: {}", *mutable_reference);} // mutable_reference goes out of scope, the lock is releasedprintln!("Outside the scope, data is: {}", *data.borrow());
}

In this example, mutable_reference is a mutable reference to the integer wrapped in data, which is a RefCell. We increment the integer by 1, and after mutable_reference goes out of scope, we can borrow data again.

Note2: The borrow() function is a method of RefCell<T> in Rust. This function is used to gain immutable access to the underlying value that the RefCell wraps around.

Similar to borrow_mut(), it provides a way to access the data inside the RefCell. The difference is that borrow() gives you an immutable reference (Ref<T>), while borrow_mut() gives you a mutable reference (RefMut<T>).

The RefCell checks at runtime to make sure the borrowing rules are not violated, which are:

  1. You may have either one mutable reference or any number of immutable references at the same time, but not both.
  2. References must always be valid.

If you try to call borrow() when the value is already mutably borrowed (through borrow_mut()), or try to call borrow_mut() when the value is immutably borrowed (through borrow()), your program will panic at runtime.

Here’s how you might use borrow():

use std::cell::RefCell;fn main() {let data = RefCell::new(5);{let mutable_reference = data.borrow_mut();*mutable_reference += 1;} // mutable_reference goes out of scope, the lock is releasedlet immutable_reference = data.borrow();println!("Data is: {}", *immutable_reference);
} 

In this example, we first use borrow_mut() to mutate the value inside data, then we use borrow() to get an immutable reference to the data.

相关文章:

Rust- 智能指针

Smart pointers A smart pointer is a data structure that not only acts like a pointer but provides additional functionality. This “smartness” comes from the fact that smart pointers encapsulate additional logical or semantic rules, which are automaticall…...

什么是微服务

微服务的架构特征&#xff1a; 单一职责&#xff1a;微服务拆分粒度更小&#xff0c;每一个服务都对应唯一的业务能力&#xff0c;做到单一职责自治&#xff1a;团队独立、技术独立、数据独立&#xff0c;独立部署和交付面向服务&#xff1a;服务提供统一标准的接口&#xff0…...

无人机电力巡检方案在电网安全与维护中的应用

目前&#xff0c;无人机技术已经在各行各业都有广泛的应用&#xff0c;其中之一就是在电力巡检中的应用。无人机电力巡检方案以其高效、安全、精准的特点&#xff0c;为电网安全与维护带来了重大突破和进步。 一、无人机电力巡检方案是高效巡检的利器 传统的电力巡检方式需要人…...

网络工程师 快速入门

需要掌握 以下技术 1.网络 基础 知识 TCP/IP 、OSI 7层协议、IP地址、ARP地址解析协议、ICMP&#xff08;英特网控制报文协议&#xff0c;ping&#xff09;等 入门面试常问问题。 2.路由 路由匹配 三原则、静态路由、OSPF路由协议。 2.交换 如何放数据&#xff1f; VLAN TRU…...

Linux系统vim查看文件中文乱码

Linux系统查看文件-cat中文正常显示 vim中文乱码 1、背景2、环境3、目的4、原因5、操作步骤5.1、修改vim编码配置 6、验证 1、背景 服务器部署业务过程中查看文件内容&#xff0c;使用cat 命令查看中文正常显示&#xff0c;使用vim命令查看显示中文乱码 cat 查看 vim 查看 …...

BladeX框架开源-工作-笔记-Docker部署-Jenkins配置

BladeX框架开源-工作-笔记-Docker部署-Jenkins配置 文章目录 BladeX框架开源-工作-笔记-Docker部署-Jenkins配置第一章-概要-BladeX框架简介与git地址第二章-BladeX框架前后端项目Docker部署与DockerFile配置文件2.1-开始部署阶段&#xff0c;默认服务器上面已有Nacos服务2.2-采…...

Modbus tcp转ETHERCAT网关modbus tcp/ip协议

捷米JM-ECT-TCP网关能够连接到Modbus tcp总线和ETHERCAT总线中&#xff0c;实现两种不同协议设备之间的通讯。这个网关能够大大提高工业生产的效率和生产效益&#xff0c;让生产变得更加智能化。捷米JM-ECT-TCP 是自主研发的一款 ETHERCAT 从站功能的通讯网关。该产品主要功能是…...

RK356x Android11更换默认的Launcher

1、 开发环境 ubuntu版本&#xff1a;18.04 开发平台&#xff1a;RK356x Android版本&#xff1a;android11 2、目的 android11 系统自带了一个启动器Launcher3&#xff0c;在android源码路径下的packages/apps/Launcher3下&#xff0c;现需要将我们自己开发的Launcher放到a…...

Python 操作 MySQL 数据库

Python 操作 MySQL 数据库 Python 标准数据库接口为 Python DB-API&#xff0c;Python DB-API为开发人员提供了数据库应用编程接口。 Python 数据库接口支持非常多的数据库&#xff0c;你可以选择适合你项目的数据库&#xff1a; GadFlymSQLMySQLPostgreSQLMicrosoft SQL Se…...

脑电信号处理与特征提取——6.运用机器学习技术和脑电进行大脑解码(涂毅恒)

目录 六、运用机器学习技术和脑电进行大脑解码 6.1 前言 6.2 基于脑电数据的机器学习基础分析 6.3 基于脑电数据的机器学习进阶分析 6.4 代码解读 六、运用机器学习技术和脑电进行大脑解码 6.1 前言 6.2 基于脑电数据的机器学习基础分析 6.3 基于脑电数据的机器学习进阶分…...

腾讯云COS+PicGO+截图工具+Obsidian+Typora+蚁小二:打造丝滑稳定的Markdown写作和分发环境

背景 很久很久以前&#xff0c;我写过一篇《有道云笔记EverythingTyporaGitHub图床PicGojsDelivr加速截图工具——创造丝滑免费的Markdown写作环境》&#xff08;https://blog.csdn.net/qq_43721542/article/details/9685957&#xff09;&#xff0c;当时的目的是打造一个云同…...

LeetCode--HOT100题(18)

目录 题目描述&#xff1a;73. 矩阵置零&#xff08;中等&#xff09;题目接口解题思路1代码解题思路2代码 PS: 题目描述&#xff1a;73. 矩阵置零&#xff08;中等&#xff09; 给定一个 m x n 的矩阵&#xff0c;如果一个元素为 0 &#xff0c;则将其所在行和列的所有元素都…...

ES6的语法兼容IE浏览器

案例1 zdsxData.zdsxData.forEach(el>{let str <tr> <td><a href${el.url} target"_blank"><font color"#79EEFF">${el.sxms}</font></a></td> <td>${el.gjjd}</td> <td>${el.zrr}<…...

【opencv学习】鼠标回调函数、鼠标控制画矩形

#include <iostream> #include <opencv2/opencv.hpp> using namespace cv; #define WinDow "程序窗口"void MouseHandle(int event, int x, int y, int flags, void* param);//鼠标回调函数 void Drawrectangle(cv::Mat& img, cv::Rect box);//矩形绘…...

Typescript面试题

文章目录 了解过TS吗&#xff1f;使用ts写一个对象属性约束说一下typescript中的泛型如何在TS中对函数的返回值进行类型约束ts和js相比有什么区别 了解过TS吗&#xff1f; ts是一种基于静态类型检查的强类型语言 let num:number20 console.log(num) console.log("str&qu…...

GB28181智能安全帽方案探究及技术实现

什么是智能安全帽&#xff1f;​ 智能安全帽是一种集成先进科技的安全帽&#xff0c;可基于GB28181规范&#xff0c;适用于铁路巡检、电力、石油化工等高风险行业的作业人员&#xff0c;以及消防、救援等紧急情况下的安全防护。 智能安全帽通常具有以下功能&#xff1a; 实时…...

【css】解决元素浮动溢出问题

如果一个元素比包含它的元素高&#xff0c;并且它是浮动的&#xff0c;它将“溢出”到其容器之外&#xff1a;然后可以向包含元素添加 overflow: auto;&#xff0c;来解决此问题&#xff1a; 代码&#xff1a; <!DOCTYPE html> <html> <head> <style>…...

SOC FPGA之流水灯设计

一、DS-5简介 Altera Soc EDS开发套件的核心是Altera版ARM Development Studio 5(DS-5)工具包&#xff0c;为SoC器件提供了完整的嵌入式开发环境、FPGA自适应调试和对Altera工具的兼容。 1.1 DS-5 eclipse破解 首先下载破解器 然后进入cmd运行&#xff0c;进入到破解器所在文…...

无涯教程-Lua - Iterators(迭代器)

迭代器是一种构造&#xff0c;使您可以遍历所谓的集合或集合的元素。在Lua中&#xff0c;这些集合通常引用表&#xff0c;这些表用于创建各种数据结构(如数组)。 通用迭代器 通用的 for 迭代器提供集合中每个元素的键值对。下面给出一个简单的示例。 array{"Lua",…...

HTML+CSS+JavaScript:实现B站评论发布效果

一、需求 1、用户输入内容&#xff0c;输入框左下角实时显示输入字数 2、为避免用户输入时在内容左右两端误按多余的空格&#xff0c;在发送评论时&#xff0c;检测用户输入的内容左右两端是否带有空格&#xff0c;若有空格&#xff0c;发布时自动取消左右两端的空格 3、若用…...

【网络】每天掌握一个Linux命令 - iftop

在Linux系统中&#xff0c;iftop是网络管理的得力助手&#xff0c;能实时监控网络流量、连接情况等&#xff0c;帮助排查网络异常。接下来从多方面详细介绍它。 目录 【网络】每天掌握一个Linux命令 - iftop工具概述安装方式核心功能基础用法进阶操作实战案例面试题场景生产场景…...

UE5 学习系列(三)创建和移动物体

这篇博客是该系列的第三篇&#xff0c;是在之前两篇博客的基础上展开&#xff0c;主要介绍如何在操作界面中创建和拖动物体&#xff0c;这篇博客跟随的视频链接如下&#xff1a; B 站视频&#xff1a;s03-创建和移动物体 如果你不打算开之前的博客并且对UE5 比较熟的话按照以…...

Mac软件卸载指南,简单易懂!

刚和Adobe分手&#xff0c;它却总在Library里给你写"回忆录"&#xff1f;卸载的Final Cut Pro像电子幽灵般阴魂不散&#xff1f;总是会有残留文件&#xff0c;别慌&#xff01;这份Mac软件卸载指南&#xff0c;将用最硬核的方式教你"数字分手术"&#xff0…...

第一篇:Agent2Agent (A2A) 协议——协作式人工智能的黎明

AI 领域的快速发展正在催生一个新时代&#xff0c;智能代理&#xff08;agents&#xff09;不再是孤立的个体&#xff0c;而是能够像一个数字团队一样协作。然而&#xff0c;当前 AI 生态系统的碎片化阻碍了这一愿景的实现&#xff0c;导致了“AI 巴别塔问题”——不同代理之间…...

基于TurtleBot3在Gazebo地图实现机器人远程控制

1. TurtleBot3环境配置 # 下载TurtleBot3核心包 mkdir -p ~/catkin_ws/src cd ~/catkin_ws/src git clone -b noetic-devel https://github.com/ROBOTIS-GIT/turtlebot3.git git clone -b noetic https://github.com/ROBOTIS-GIT/turtlebot3_msgs.git git clone -b noetic-dev…...

代码随想录刷题day30

1、零钱兑换II 给你一个整数数组 coins 表示不同面额的硬币&#xff0c;另给一个整数 amount 表示总金额。 请你计算并返回可以凑成总金额的硬币组合数。如果任何硬币组合都无法凑出总金额&#xff0c;返回 0 。 假设每一种面额的硬币有无限个。 题目数据保证结果符合 32 位带…...

动态 Web 开发技术入门篇

一、HTTP 协议核心 1.1 HTTP 基础 协议全称 &#xff1a;HyperText Transfer Protocol&#xff08;超文本传输协议&#xff09; 默认端口 &#xff1a;HTTP 使用 80 端口&#xff0c;HTTPS 使用 443 端口。 请求方法 &#xff1a; GET &#xff1a;用于获取资源&#xff0c;…...

C/C++ 中附加包含目录、附加库目录与附加依赖项详解

在 C/C 编程的编译和链接过程中&#xff0c;附加包含目录、附加库目录和附加依赖项是三个至关重要的设置&#xff0c;它们相互配合&#xff0c;确保程序能够正确引用外部资源并顺利构建。虽然在学习过程中&#xff0c;这些概念容易让人混淆&#xff0c;但深入理解它们的作用和联…...

人工智能--安全大模型训练计划:基于Fine-tuning + LLM Agent

安全大模型训练计划&#xff1a;基于Fine-tuning LLM Agent 1. 构建高质量安全数据集 目标&#xff1a;为安全大模型创建高质量、去偏、符合伦理的训练数据集&#xff0c;涵盖安全相关任务&#xff08;如有害内容检测、隐私保护、道德推理等&#xff09;。 1.1 数据收集 描…...

android RelativeLayout布局

<?xml version"1.0" encoding"utf-8"?> <RelativeLayout xmlns:android"http://schemas.android.com/apk/res/android"android:layout_width"match_parent"android:layout_height"match_parent"android:gravity&…...