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

博物馆门户网站建设深圳关键词推广

博物馆门户网站建设,深圳关键词推广,北京不限购二环小公寓,做网站的流程分析-图灵吧目录 一、概念二、Box\<T\>2.1 概念与应用场景2.2 简单应用2.3 递归类型的创建 三、通过Deref trait将智能指针当作常规引用处理3.1 常规引用3.2 像引用一样使用Box\<T\>3.3 自定义智能指针3.4 函数和方法的隐式解引用强制转换3.5 解引用强制转换与可变性交互 四、…

目录

  • 一、概念
  • 二、Box\<T\>
    • 2.1 概念与应用场景
    • 2.2 简单应用
    • 2.3 递归类型的创建
  • 三、通过Deref trait将智能指针当作常规引用处理
    • 3.1 常规引用
    • 3.2 像引用一样使用Box\<T\>
    • 3.3 自定义智能指针
    • 3.4 函数和方法的隐式解引用强制转换
    • 3.5 解引用强制转换与可变性交互
  • 四、使用Drop Trait清理代码
    • 4.1 自动运行
    • 4.2 手动丢弃

一、概念

  • 在Rust中,引用是只是借用数据的指针,智能指针拥有它们所指向的数据的所有权;
  • 智能指针通常使用结构体实现;
  • 智能指针实现了Deref trait,值可以被当作引用对待;
  • 智能指针实现了Drop trait,当值离开作用域时,其所指向的堆数据也去被清除;
  • 常用的智能指针见下表
指针功能说明
Box<T>用于在堆上分配值,允许在编译时执行不可变或可变借用检查
Rc<T>一个引用计数类型,相同数据可以有多个所有者,仅允许在编译时执行不可变借用检查
RefCell<T>允许在运行时执行不可变或可变借用检查;可以在即使RefCell<T> 自身是不可变的情况下修改其内部的值
Ref<T>RefMut<T>通过RefCell<T> 访问
  • 内部可变性模式:在不可变值内部改变值;

二、Box<T>

2.1 概念与应用场景

  • box是最简单最直接的智能指针,其类型是box<T>
  • box主要应用于以下场景:
    • 编译时未知大小的类型,但使用时却需要知道它的确切大小;
    • 大量数据且希望在确保数据不被拷贝的情况下转移所有权;
    • 只关心值的类型是否实现了特定 trait;

2.2 简单应用

fn main(){let b = Box::new(5);println!("b = {}", b);
}
  • 变量b指向了分配在上的值为5的Box;
  • b拥有这块内存的所有权,离开作用域后堆内存被自动释放;

2.3 递归类型的创建

  • Rust需要在编译时知道类型占用的空间大小;
  • box的已知大小,让其可以在循环类型定义中插入box,就可以创建递归类型;
enum List{Cons(i32, Box<List>),Nil,
}use crate::List::{Cons, Nil};
fn main() {let list = Cons(1,Box::new(Cons(2, Box::new(Cons(3, Box::new(Nil))))));
}
  • Cons成员将需要一个i32类型的空间大小以及box指针数据的空间;
  • Nil成员不存储值,因此它比Cons成员需要更少的空间;
  • 看起来像这样

在这里插入图片描述

  • 如果不用Box定义递归,写成下面这样

enum List{Cons(i32, List),Nil,
}use crate::List::{Cons, Nil};
fn main() {let list = Cons(1, Cons(2, Cons(3, Nil)));
}
  • 则编译报错,表明类型占用的空间无限大

在这里插入图片描述

  • 其空间排布类型于

在这里插入图片描述

三、通过Deref trait将智能指针当作常规引用处理

  • 实现Deref trait可以让使用者重载解引用运算符(dereference operator) *
  • 这种方式实现Deref trait的智能指针可以被当作常规引用来对待,可以编写操作引用的代码并用于智能指针;

3.1 常规引用

  • 常规引用是一种指针类型;
fn main() {let x = 5;let y = &x;assert_eq!(5, x);assert_eq!(5, *y);
}
  • y等于x的引用,使用*y访问x的值;

3.2 像引用一样使用Box<T>

    let x = 5;let y = Box::new(x);assert_eq!(5, x);assert_eq!(5, *y);
  • 代码可正常运行不报错;

3.3 自定义智能指针

use std::ops::Deref;struct MyBox<T>(T);impl<T> MyBox<T> {fn new(x: T) -> MyBox<T> {MyBox(x)}
}impl<T> Deref for MyBox<T>{type Target = T;fn deref(&self) -> &T {&self.0}
}fn main() {let x = 5;let y = MyBox::new(x);assert_eq!(5, x);assert_eq!(5, *y);
}
  • MyBox<T> 被定义为包含一个元素的元组结构体;
  • new函数获取一个T类型的参数并返回一个存入传入值的实例;
  • 为MyBox实现Deref trait才能启动*运算符的解引用功能;
  • impl<T> Deref for MyBox<T>中的type Target = T 定义了此trait的关联类型;
  • deref方法返回了一个值的引用,如果直接返回值,则值的选择权将被移出self;
  • 当使用*y时,底层运行了代码*(y.deref())

3.4 函数和方法的隐式解引用强制转换

  • 解引用强制转换只能工作在实现了Dereftrait 的类型上;
  • 解引用强制转换是将一种类型隐式转换为另外一种类型的引用;
  • 前一种类型实现了Dereftrait,并且其关联类型是后一种类型;

例如,解引用强制转换可以将 &String 转换为 &str,因为类型 String 实现了 Deref trait 并且其关联类型是 str;

#[stable(feature = "rust1", since = "1.0.0")]
impl ops::Deref for String {type Target = str;#[inline]fn deref(&self) -> &str {unsafe { str::from_utf8_unchecked(&self.vec) }}
}
  • 将特定类型的值的引用传递给函数且与函数定义的参数类型不匹配时,会发生解引用强制转换
  • 此时有一系列的deref方法被调用,将我们提供的参数类型转换成函数或方法需要的参数类型;
  • 解引用强制转换功能可以让开发者编写函数和方法调用时无需增加过多显式使用&和*引用和解引用。
  • 解引用强制转换功能也使得开发者可以编写更多同时作用于引用或智能指针的代码;
use std::ops::Deref;struct MyBox<T>(T);impl<T> MyBox<T> {fn new(x: T) -> MyBox<T> {MyBox(x)}
}impl<T> Deref for MyBox<T>{type Target = T;fn deref(&self) -> &T {&self.0}
}fn hello(name: &str){println!("Hello, {}", name);
}fn main() {let m = MyBox::new(String::from("Rust"));hello(&m);
}
  • main函数中的m为MyBox<String>值的引用;
  • MyBox<T>上实现了Dereftrait,Rust可以通过deref调用将&MyBox<String>变为&String
  • 再次调用deref将&String 变为 &str;
  • 如果没有实现解引用强制转换,为了使用&MyBox<String>类型的值调用hello函数,应该这样写
fn main() {let m = MyBox::new(String::from("Rust"));hello(&(*m)[..]);
}
  • (*m) 将 MyBox<String> 解引用为 String;
  • &和[…] 获取了整个 String 的字符串 slice 来匹配 hello 函数的参数;
  • 没有解引用强制转换所有这些符号混在一起将更难以读写和理解;
  • Rust的解引用强制转换发生在编译,因此在运行时没有损耗!

3.5 解引用强制转换与可变性交互

  • 类似于使用 Deref trait 重载不可变引用的*运算符,Rust提供了DerefMut trait用于重载可变引用的*运算符;
  • Rust 在发现类型和 trait 的实现满足以下三种情况时会进行解引用强制转换;
    1. 当 T: Deref<Target=U> :从 &T 到 &U
      如果有一个&T,而T实现了返回U类型的Deref,则可以直接得到&U
    2. 当 T: DerefMut<Target=U> :从 &mut T 到 &mut U
      对于可变引用有着与第一种相同的行为;
    3. 当 T: Deref<Target=U> :从 &mut T 到 &U
      Rust也会将可变引用强转为不可变引用,但是反之是不可能的,因为不可变引用永远也不能强转为可变引用;

四、使用Drop Trait清理代码

4.1 自动运行

  • 通过实现Droptrait指定变量离开作用域时被执行的代码;
  • 可以理解为析构函数;
struct CustomSmartPointer {data: String,
}impl Drop for CustomSmartPointer {fn drop(&mut self) {println!("Dropping CustomSmartPointer with data `{}`!", self.data);}
}fn main() {{let c = CustomSmartPointer { data: String::from("stuff c") };}let d = CustomSmartPointer { data: String::from("stuff d") };let e = CustomSmartPointer { data: String::from("stuff e") };println!("CustomSmartPointers created.");
}
  • main函数中离开最内层的大括号后,变量c首先离开作用域,自动调用drop方法;
  • 然后打印CustomSmartPointers created.
  • 变量d、e最后离开作用域,再自动调用对应的drop方法;
  • d、e的输出结果显示,以先进后出的方式调用drop方法;

在这里插入图片描述

4.2 手动丢弃

  • 不能显式的调用drop方法;
  • 如果要在作用域结构之前强制释放变量,使用drop(x)实现;
fn main() {{let c = CustomSmartPointer { data: String::from("stuff c") };}let d = CustomSmartPointer { data: String::from("stuff d") };drop(d);let e = CustomSmartPointer { data: String::from("stuff e") };println!("CustomSmartPointers created.");
}

运行代码,可以发现d被提前析构;
在这里插入图片描述

http://www.hkea.cn/news/307089/

相关文章:

  • 国外比较好的资源网站电商运营推广是做什么的
  • 佛山房地产网站建设seo实战培训王乃用
  • 如何做可以赚钱的网站关键词如何快速排名
  • 深圳品牌做网站公司有哪些百度app推广
  • 重庆建设行业信息网站搜狗登录入口
  • 同仁行业网站建设报价北京做的好的seo公司
  • 陕西自助建站做网站郑州外语网站建站优化
  • 小型企业网站系统cilimao磁力猫最新版地址
  • 铁岭网站建设移动网站广东网站seo
  • 网站模板插件sem和seo
  • 用wordpress制作网站模板沈阳seo
  • 优化一个网站多少钱宜昌网站seo
  • 刚做的网站怎么才能搜索到枸橼酸西地那非片功效效及作用
  • 罗湖区网站公司专业模板建站
  • 哪有备案好的网站国产系统2345
  • 网站开发怎么让别人看到最新营销模式有哪些
  • ssm网站开发源码百度推广多少钱一个月
  • 手游门户网站建设appstore关键词优化
  • 齐河网站开发seo服务内容
  • 北京微信网站建设费用想卖产品怎么推广宣传
  • 网站上线的步骤厦门网站推广公司哪家好
  • 网站做app的软件有哪些百度一下你就知道下载
  • 界面设计的重要性百度seo关键词排名推荐
  • 股票做T网站直播营销
  • 北京手机网站建设公司排名技术优化seo
  • wordpress可爱的主题seo优化教程
  • 自己可以申请网站做外卖吗网站描述和关键词怎么写
  • 公司网站网页设计seo站长工具推广平台
  • 重庆南岸营销型网站建设公司哪家专业真实的网站制作
  • 郑州企业网站建设兼职推广渠道