【Rust】写时复制Cow

2024-03-09 13:32
文章标签 rust cow 复制 写时

本文主要是介绍【Rust】写时复制Cow,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

写时复制(Copy on Write)技术是一种程序中的优化策略,多应用于读多写少的场景。主要思想是创建对象的时候不立即进行复制,而是先引用(借用)原有对象进行大量的读操作,只有进行到少量的写操作的时候,才进行复制操作,将原有对象复制后再写入。这样的好处是在读多写少的场景下,减少了复制操作,提高了性能。

Rust中对应这种思想的是智能指针Cow<T>,定义如下:

pub enum Cow<'a, B> 
whereB: 'a + ToOwned + 'a + ?Sized, {Borrowed(&'a B),    //用于包裹引用Owned(<B as ToOwned>::Owned),   //用于包裹所有者
}

可以看到是一个枚举体,包括两个可选值,一个是“借用”,一个是“所有”。具体含义是:以不可变的方式访问借用内容,在需要可变借用或所有权的时候再克隆一份数据。

下面举个例子说明Cow<T>的应用:

use std::borrow::Cow;fn abs_all(input: &mut Cow<[i32]>) {for i in 0..input.len() {let v = input[i];if v < 0 {input.to_mut()[i] = -v;}}println!("value: {:?}", input);
}fn main() {// 只读,不写,没有发生复制操作let a = [0, 1, 2];let mut input = Cow::from(&a[..]);abs_all(&mut input);assert_eq!(input, Cow::Borrowed(a.as_ref()));// 写时复制, 在读到-1的时候发生复制let b = [0, -1, -2];let mut input = Cow::from(&b[..]);abs_all(&mut input);assert_eq!(input, Cow::Owned(vec![0,1,2]) as Cow<[i32]>);// 没有写时复制,因为已经拥有所有权let mut input = Cow::from(vec![0, -1, -2]);abs_all(&mut input);assert_eq!(input, Cow::Owned(vec![0,1,2]) as Cow<[i32]>);let v = input.into_owned();assert_eq!(v, [0, 1, 2]);
}

上面这个用例已经讲明了Cow<T>的使用,下面我们继续探索一下Cow<T>的实现细节。重点关注to_mutinto_owned的实现。

  • to_mut :就是返回数据的可变引用,如果没有数据的所有权,则复制拥有后再返回可变引用;
  • into_owned :获取一个拥有所有权的对象(区别与引用),如果当前是借用,则发生复制,创建新的所有权对象,如果已拥有所有权,则转移至新对象。
impl<B: ?Sized + ToOwned> Cow<'_, B> {#[stable(feature = "rust1", since = "1.0.0")]pub fn to_mut(&mut self) -> &mut <B as ToOwned>::Owned {// 如果时借用,则进行复制;如果已拥有所有权,则无需进行复制match *self {Borrowed(borrowed) => {*self = Owned(borrowed.to_owned());match *self {Borrowed(..) => unreachable!(),Owned(ref mut owned) => owned,}}   Owned(ref mut owned) => owned,  //这里解释了上个例子中,已拥有所有权的情况,无需再复制}}#[stable(feature = "rust1", since = "1.0.0")]pub fn into_owned(self) -> <B as ToOwned>::Owned {// 如果当前是借用,则发生复制,创建新的所有权对象,如果已拥有所有权,则转移至新对象。match self {Borrowed(borrowed) => borrowed.to_owned(),Owned(owned) => owned,}}
}

这篇关于【Rust】写时复制Cow的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/790819

相关文章

Linux使用scp进行远程目录文件复制的详细步骤和示例

《Linux使用scp进行远程目录文件复制的详细步骤和示例》在Linux系统中,scp(安全复制协议)是一个使用SSH(安全外壳协议)进行文件和目录安全传输的命令,它允许在远程主机之间复制文件和目录,... 目录1. 什么是scp?2. 语法3. 示例示例 1: 复制本地目录到远程主机示例 2: 复制远程主

Mysql的主从同步/复制的原理分析

《Mysql的主从同步/复制的原理分析》:本文主要介绍Mysql的主从同步/复制的原理分析,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录为什么要主从同步?mysql主从同步架构有哪些?Mysql主从复制的原理/整体流程级联复制架构为什么好?Mysql主从复制注意

Python实现自动化Word文档样式复制与内容生成

《Python实现自动化Word文档样式复制与内容生成》在办公自动化领域,高效处理Word文档的样式和内容复制是一个常见需求,本文将展示如何利用Python的python-docx库实现... 目录一、为什么需要自动化 Word 文档处理二、核心功能实现:样式与表格的深度复制1. 表格复制(含样式与内容)2

一文详解PostgreSQL复制参数

《一文详解PostgreSQL复制参数》PostgreSQL作为一款功能强大的开源关系型数据库,其复制功能对于构建高可用性系统至关重要,本文给大家详细介绍了PostgreSQL的复制参数,需要的朋友可... 目录一、复制参数基础概念二、核心复制参数深度解析1. max_wal_seChina编程nders:WAL

rust 中的 EBNF简介举例

《rust中的EBNF简介举例》:本文主要介绍rust中的EBNF简介举例,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧... 目录1. 什么是 EBNF?2. 核心概念3. EBNF 语法符号详解4. 如何阅读 EBNF 规则5. 示例示例 1:简单的电子邮件地址

SQL常用操作精华之复制表、跨库查询、删除重复数据

《SQL常用操作精华之复制表、跨库查询、删除重复数据》:本文主要介绍SQL常用操作精华之复制表、跨库查询、删除重复数据,这些SQL操作涵盖了数据库开发中最常用的技术点,包括表操作、数据查询、数据管... 目录SQL常用操作精华总结表结构与数据操作高级查询技巧SQL常用操作精华总结表结构与数据操作复制表结

使用FileChannel实现文件的复制和移动方式

《使用FileChannel实现文件的复制和移动方式》:本文主要介绍使用FileChannel实现文件的复制和移动方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐... 目录使用 FileChannel 实现文件复制代码解释使用 FileChannel 实现文件移动代码解释

通过Python脚本批量复制并规范命名视频文件

《通过Python脚本批量复制并规范命名视频文件》本文介绍了如何通过Python脚本批量复制并规范命名视频文件,实现自动补齐数字编号、保留原始文件、智能识别有效文件等功能,听过代码示例介绍的非常详细,... 目录一、问题场景:杂乱的视频文件名二、完整解决方案三、关键技术解析1. 智能路径处理2. 精准文件名

linux如何复制文件夹并重命名

《linux如何复制文件夹并重命名》在Linux系统中,复制文件夹并重命名可以通过使用“cp”和“mv”命令来实现,使用“cp-r”命令可以递归复制整个文件夹及其子文件夹和文件,而使用“mv”命令可以... 目录linux复制文件夹并重命名我们需要使用“cp”命令来复制文件夹我们还可以结合使用“mv”命令总

Rust中的注释使用解读

《Rust中的注释使用解读》本文介绍了Rust中的行注释、块注释和文档注释的使用方法,通过示例展示了如何在实际代码中应用这些注释,以提高代码的可读性和可维护性... 目录Rust 中的注释使用指南1. 行注释示例:行注释2. 块注释示例:块注释3. 文档注释示例:文档注释4. 综合示例总结Rust 中的注释